This Git documentation is based on Git 2.50.1. The up to date Git reference can be found on https://git-scm.com/docs/
git [-v | --version] [-h | --help] [-C <path>] [-c <name>=<value>]
[--exec-path[=<path>]] [--html-path] [--man-path] [--info-path]
[-p | --paginate | -P | --no-pager] [--no-replace-objects] [--no-lazy-fetch]
[--no-optional-locks] [--no-advice] [--bare] [--git-dir=<path>]
[--work-tree=<path>] [--namespace=<name>] [--config-env=<name>=<envvar>]
<command> [<args>]
Git is a fast, scalable, distributed revision control system with an unusually rich command set that provides both high-level operations and full access to internals.
See the section called “gittutorial(7)” to get started, then see the section called “giteveryday(7)” for a useful minimum set of commands. The Git User's Manual has a more in-depth introduction.
After you mastered the basic concepts, you can come back to this page to learn what commands Git offers. You can learn more about individual Git commands with "git help command". the section called “gitcli(7)” manual page gives you an overview of the command-line command syntax.
A formatted and hyperlinked copy of the latest Git documentation can be viewed at https://git.github.io/htmldocs/git.html or https://git-scm.com/docs.
Prints the Git suite version that the git program came from.
This option is internally converted to git version ... and accepts the same options as the the section called “git-version(1)” command. If --help is also given, it takes precedence over --version.
Prints the synopsis and a list of the most commonly used commands. If the option --all or -a is given then all available commands are printed. If a Git command is named this option will bring up the manual page for that command.
Other options are available to control how the manual page is displayed. See the section called “git-help(1)” for more information, because git --help ... is converted internally into git help ....
Run as if git was started in <path> instead of the current working directory. When multiple -C options are given, each subsequent non-absolute -C <path> is interpreted relative to the preceding -C <path>. If <path> is present but empty, e.g. -C "", then the current working directory is left unchanged.
This option affects options that expect path name like --git-dir and --work-tree in that their interpretations of the path names would be made relative to the working directory caused by the -C option. For example the following invocations are equivalent:
git --git-dir=a.git --work-tree=b -C c status git --git-dir=c/a.git --work-tree=c/b status
Pass a configuration parameter to the command. The value given will override values from configuration files. The <name> is expected in the same format as listed by git config (subkeys separated by dots).
Note that omitting the = in git -c foo.bar ... is allowed and sets foo.bar to the boolean true value (just like [foo]bar would in a config file). Including the equals but with an empty value (like git -c foo.bar= ...) sets foo.bar to the empty string which git config --type=bool will convert to false.
Like -c <name>=<value>, give configuration variable <name> a value, where <envvar> is the name of an environment variable from which to retrieve the value. Unlike -c there is no shortcut for directly setting the value to an empty string, instead the environment variable itself must be set to the empty string. It is an error if the <envvar> does not exist in the environment. <envvar> may not contain an equals sign to avoid ambiguity with <name> containing one.
This is useful for cases where you want to pass transitory configuration options to git, but are doing so on operating systems where other processes might be able to read your command line (e.g. /proc/self/cmdline), but not your environment (e.g. /proc/self/environ). That behavior is the default on Linux, but may not be on your system.
Note that this might add security for variables such as http.extraHeader where the sensitive information is part of the value, but not e.g. url.<base>.insteadOf where the sensitive information can be part of the key.
Set the path to the repository (".git" directory). This can also be controlled by setting the GIT_DIR environment variable. It can be an absolute path or relative path to current working directory.
Specifying the location of the ".git" directory using this option (or GIT_DIR environment variable) turns off the repository discovery that tries to find a directory with ".git" subdirectory (which is how the repository and the top-level of the working tree are discovered), and tells Git that you are at the top level of the working tree. If you are not at the top-level directory of the working tree, you should tell Git where the top-level of the working tree is, with the --work-tree=<path> option (or GIT_WORK_TREE environment variable)
If you just want to run git as if it was started in <path> then use git -C <path>.
We divide Git into high level ("porcelain") commands and low level ("plumbing") commands.
We separate the porcelain commands into the main commands and some ancillary user utilities.
Manipulators:
Interrogators:
These commands are to interact with foreign SCM and with other people via patch over e-mail.
There are three commands with similar names: git reset, git restore and git revert.
the section called “git-reset(1)” is about updating your branch, moving the tip in order to add or remove commits from the branch. This operation changes the commit history.
git reset can also be used to restore the index, overlapping with git restore.
Although Git includes its own porcelain layer, its low-level commands are sufficient to support development of alternative porcelains. Developers of such porcelains might start by reading about the section called “git-update-index(1)” and the section called “git-read-tree(1)”.
The interface (input, output, set of options and the semantics) to these low-level commands are meant to be a lot more stable than Porcelain level commands, because these commands are primarily for scripted use. The interface to Porcelain commands on the other hand are subject to change in order to improve the end user experience.
The following description divides the low-level commands into commands that manipulate objects (in the repository, index, and working tree), commands that interrogate and compare objects, and commands that move objects and references between repositories.
In general, the interrogate commands do not touch the files in the working tree.
The following are helper commands used by the above; end users typically do not use them directly.
These are internal helper commands used by other commands; end users typically do not use them directly.
The following documentation pages are guides about Git concepts.
This documentation discusses repository and command interfaces which users are expected to interact with directly. See --user-formats in the section called “git-help(1)” for more details on the criteria.
This documentation discusses file formats, over-the-wire protocols and other git developer interfaces. See --developer-interfaces in the section called “git-help(1)”.
Git uses a simple text format to store customizations that are per repository and are per user. Such a configuration file may look like this:
#
# A '#' or ';' character indicates a comment.
#
; core variables
[core]
; Don't trust file modes
filemode = false
; user identity
[user]
name = "Junio C Hamano"
email = "gitster@pobox.com"Various commands read from the configuration file and adjust their operation accordingly. See the section called “git-config(1)” for a list and more details about the configuration mechanism.
Any Git command accepting any <object> can also use the following symbolic notation:
For a more complete list of ways to spell object names, see "SPECIFYING REVISIONS" section in the section called “gitrevisions(7)”.
Please see the the section called “gitrepository-layout(5)” document.
Read the section called “githooks(5)” for more details about each hook.
Higher level SCMs may provide and manage additional information in the $GIT_DIR.
Please see the section called “gitglossary(7)”.
Various Git commands pay attention to environment variables and change their behavior. The environment variables marked as "Boolean" take their values the same way as Boolean valued configuration variables, i.e., "true", "yes", "on" and positive numbers are taken as "yes", while "false", "no", "off", and "0" are taken as "no".
Here are the variables:
These environment variables apply to all core Git commands. Nb: it is worth noting that they may be used/overridden by SCMS sitting above Git so take care if using a foreign front-end.
Due to the immutable nature of Git objects, old objects can be archived into shared, read-only directories. This variable specifies a ":" separated (on Windows ";" separated) list of Git object directories which can be used to search for Git objects. New objects will not be written to these directories.
Entries that begin with " (double-quote) will be interpreted as C-style quoted paths, removing leading and trailing double-quotes and respecting backslash escapes. E.g., the value "path-with-\"-and-:-in-it":vanilla-path has two paths: path-with-"-and-:-in-it and vanilla-path.
When the environment variable GIT_EXTERNAL_DIFF is set, the program named by it is called to generate diffs, and Git does not use its builtin diff machinery. For a path that is added, removed, or modified, GIT_EXTERNAL_DIFF is called with 7 parameters:
path old-file old-hex old-mode new-file new-hex new-mode
where:
are the octal representation of the file modes.
The file parameters can point at the user's working file (e.g. new-file in "git-diff-files"), /dev/null (e.g. old-file when a new file is added), or a temporary file (e.g. old-file in the index). GIT_EXTERNAL_DIFF should not worry about unlinking the temporary file -- it is removed when GIT_EXTERNAL_DIFF exits.
For a path that is unmerged, GIT_EXTERNAL_DIFF is called with 1 parameter, <path>.
For each path GIT_EXTERNAL_DIFF is called, two environment variables, GIT_DIFF_PATH_COUNTER and GIT_DIFF_PATH_TOTAL are set.
If either of these environment variables is set then git fetch and git push will use the specified command instead of ssh when they need to connect to a remote system. The command-line parameters passed to the configured command are determined by the ssh variant. See ssh.variant option in the section called “git-config(1)” for details.
$GIT_SSH_COMMAND takes precedence over $GIT_SSH, and is interpreted by the shell, which allows additional arguments to be included. $GIT_SSH on the other hand must be just the path to a program (which can be a wrapper shell script, if additional arguments are needed).
Usually it is easier to configure any desired options through your personal .ssh/config file. Please consult your ssh documentation for further details.
Enables general trace messages, e.g. alias expansion, built-in command execution and external command execution.
If this variable is set to "1", "2" or "true" (comparison is case insensitive), trace messages will be printed to stderr.
If the variable is set to an integer value greater than 2 and lower than 10 (strictly) then Git will interpret this value as an open file descriptor and will try to write the trace messages into this file descriptor.
Alternatively, if the variable is set to an absolute path (starting with a / character), Git will interpret this as a file path and will try to append the trace messages to it.
Unsetting the variable, or setting it to empty, "0" or "false" (case insensitive) disables trace messages.
Enables tracing of packfiles sent or received by a given program. Unlike other trace output, this trace is verbatim: no headers, and no quoting of binary data. You almost certainly want to direct into a file (e.g., GIT_TRACE_PACKFILE=/tmp/my.pack) rather than displaying it on the terminal or mixing it with other trace output.
Note that this is currently only implemented for the client side of clones and fetches.
Enables more detailed trace messages from the "trace2" library. Output from GIT_TRACE2 is a simple text-based format for human readability.
If this variable is set to "1", "2" or "true" (comparison is case insensitive), trace messages will be printed to stderr.
If the variable is set to an integer value greater than 2 and lower than 10 (strictly) then Git will interpret this value as an open file descriptor and will try to write the trace messages into this file descriptor.
Alternatively, if the variable is set to an absolute path (starting with a / character), Git will interpret this as a file path and will try to append the trace messages to it. If the path already exists and is a directory, the trace messages will be written to files (one per process) in that directory, named according to the last component of the SID and an optional counter (to avoid filename collisions).
In addition, if the variable is set to af_unix:[<socket-type>:]<absolute-pathname>, Git will try to open the path as a Unix Domain Socket. The socket type can be either stream or dgram.
Unsetting the variable, or setting it to empty, "0" or "false" (case insensitive) disables trace messages.
See Trace2 documentation for full details.
When loading a commit object from the commit-graph, Git performs an existence check on the object in the object database. This is done to avoid issues with stale commit-graphs that contain references to already-deleted commits, but comes with a performance penalty.
The default is "false", which disables the aforementioned behavior. Setting this to "true" enables the existence check so that stale commits will never be returned from the commit-graph at the cost of performance.
For internal use only. Used in handshaking the wire protocol. Contains a colon : separated list of keys with optional values <key>[=<value>]. Presence of unknown keys and values must be ignored.
Note that servers may need to be configured to allow this variable to pass over some transports. It will be propagated automatically when accessing local repositories (i.e., file:// or a filesystem path), as well as over the git:// protocol. For git-over-http, it should work automatically in most configurations, but see the discussion in the section called “git-http-backend(1)”. For git-over-ssh, the ssh server may need to be configured to allow clients to pass this variable (e.g., by using AcceptEnv GIT_PROTOCOL with OpenSSH).
This configuration is optional. If the variable is not propagated, then clients will fall back to the original "v0" protocol (but may miss out on some performance improvements or features). This variable currently only affects clones and fetches; it is not yet used for pushes (but may be in the future).
Windows-only: allow redirecting the standard input/output/error handles to paths specified by the environment variables. This is particularly useful in multi-threaded applications where the canonical way to pass standard handles via CreateProcess() is not an option because it would require the handles to be marked inheritable (and consequently every spawned process would inherit them, possibly blocking regular Git operations). The primary intended use case is to use named pipes for communication (e.g. \\.\pipe\my-git-stdin-123).
Two special values are supported: off will simply close the corresponding standard handle, and if GIT_REDIRECT_STDERR is 2>&1, standard error will be redirected to the same handle as standard output.
More detail on the following is available from the Git concepts chapter of the user-manual and the section called “gitcore-tutorial(7)”.
A Git project normally consists of a working directory with a ".git" subdirectory at the top level. The .git directory contains, among other things, a compressed object database representing the complete history of the project, an "index" file which links that history to the current contents of the working tree, and named pointers into that history such as tags and branch heads.
The object database contains objects of three main types: blobs, which hold file data; trees, which point to blobs and other trees to build up directory hierarchies; and commits, which each reference a single tree and some number of parent commits.
The commit, equivalent to what other systems call a "changeset" or "version", represents a step in the project's history, and each parent represents an immediately preceding step. Commits with more than one parent represent merges of independent lines of development.
All objects are named by the SHA-1 hash of their contents, normally written as a string of 40 hex digits. Such names are globally unique. The entire history leading up to a commit can be vouched for by signing just that commit. A fourth object type, the tag, is provided for this purpose.
When first created, objects are stored in individual files, but for efficiency may later be compressed together into "pack files".
Named pointers called refs mark interesting points in history. A ref may contain the SHA-1 name of an object or the name of another ref (the latter is called a "symbolic ref"). Refs with names beginning refs/head/ contain the SHA-1 name of the most recent commit (or "head") of a branch under development. SHA-1 names of tags of interest are stored under refs/tags/. A symbolic ref named HEAD contains the name of the currently checked-out branch.
The index file is initialized with a list of all paths and, for each path, a blob object and a set of attributes. The blob object represents the contents of the file as of the head of the current branch. The attributes (last modified time, size, etc.) are taken from the corresponding file in the working tree. Subsequent changes to the working tree can be found by comparing these attributes. The index may be updated with new content, and new commits may be created from the content stored in the index.
The index is also capable of storing multiple entries (called "stages") for a given pathname. These stages are used to hold the various unmerged version of a file when a merge is in progress.
Some configuration options and hook files may cause Git to run arbitrary shell commands. Because configuration and hooks are not copied using git clone, it is generally safe to clone remote repositories with untrusted content, inspect them with git log, and so on.
However, it is not safe to run Git commands in a .git directory (or the working tree that surrounds it) when that .git directory itself comes from an untrusted source. The commands in its config and hooks are executed in the usual way.
By default, Git will refuse to run when the repository is owned by someone other than the user running the command. See the entry for safe.directory in the section called “git-config(1)”. While this can help protect you in a multi-user environment, note that you can also acquire untrusted repositories that are owned by you (for example, if you extract a zip file or tarball from an untrusted source). In such cases, you'd need to "sanitize" the untrusted repository first.
If you have an untrusted .git directory, you should first clone it with git clone --no-local to obtain a clean copy. Git does restrict the set of options and hooks that will be run by upload-pack, which handles the server side of a clone or fetch, but beware that the surface area for attack against upload-pack is large, so this does carry some risk. The safest thing is to serve the repository as an unprivileged user (either via the section called “git-daemon(1)”, ssh, or using other tools to change user ids). See the discussion in the SECURITY section of the section called “git-upload-pack(1)”.
See the references in the "description" section to get started using Git. The following is probably more detail than necessary for a first-time user.
The Git concepts chapter of the user-manual and the section called “gitcore-tutorial(7)” both provide introductions to the underlying Git architecture.
See the section called “gitworkflows(7)” for an overview of recommended workflows.
See also the howto documents for some useful examples.
The internals are documented in the Git API documentation.
Users migrating from CVS may also want to read the section called “gitcvs-migration(7)”.
Git was started by Linus Torvalds, and is currently maintained by Junio C Hamano. Numerous contributions have come from the Git mailing list <git@vger.kernel.org>. https://openhub.net/p/git/contributors/summary gives you a more complete list of contributors.
If you have a clone of git.git itself, the output of the section called “git-shortlog(1)” and the section called “git-blame(1)” can show you the authors for specific parts of the project.
Report bugs to the Git mailing list <git@vger.kernel.org> where the development and maintenance is primarily done. You do not have to be subscribed to the list to send a message there. See the list archive at https://lore.kernel.org/git for previous bug reports and other discussions.
Issues which are security relevant should be disclosed privately to the Git Security mailing list <git-security@googlegroups.com>.
the section called “gittutorial(7)”, the section called “gittutorial-2(7)”, the section called “giteveryday(7)”, the section called “gitcvs-migration(7)”, the section called “gitglossary(7)”, the section called “gitcore-tutorial(7)”, the section called “gitcli(7)”, The Git User's Manual, the section called “gitworkflows(7)”
Part of the the section called “git(1)” suite
gitadd[--verbose|-v] [--dry-run|-n] [--force|-f] [--interactive|-i] [--patch|-p]
[--edit|-e] [--[no-]all|-A|--[no-]ignore-removal| [--update|-u]] [--sparse]
[--intent-to-add|-N] [--refresh] [--ignore-errors] [--ignore-missing] [--renormalize]
[--chmod=(+|-)x] [--pathspec-from-file=<file> [--pathspec-file-nul]]
[--] [<pathspec>…]
This command updates the index using the current content found in the working tree, to prepare the content staged for the next commit. It typically adds the current content of existing paths as a whole, but with some options it can also be used to add content with only part of the changes made to the working tree files applied, or remove paths that do not exist in the working tree anymore.
The "index" holds a snapshot of the content of the working tree, and it is this snapshot that is taken as the contents of the next commit. Thus after making any changes to the working tree, and before running the commit command, you must use the add command to add any new or modified files to the index.
This command can be performed multiple times before a commit. It only adds the content of the specified file(s) at the time the add command is run; if you want subsequent changes included in the next commit, then you must run git add again to add the new content to the index.
The git status command can be used to obtain a summary of which files have changes that are staged for the next commit.
The git add command will not add ignored files by default. If any ignored files were explicitly specified on the command line, git add will fail with a list of ignored files. Ignored files reached by directory recursion or filename globbing performed by Git (quote your globs before the shell) will be silently ignored. The git add command can be used to add ignored files with the -f (force) option.
Please see the section called “git-commit(1)” for alternative ways to add content to a commit.
Files to add content from. Fileglobs (e.g. *.c) can be given to add all matching files. Also a leading directory name (e.g. dir to add dir/file1 and dir/file2) can be given to update the index to match the current state of the directory as a whole (e.g. specifying dir will record not just a file dir/file1 modified in the working tree, a file dir/file2 added to the working tree, but also a file dir/file3 removed from the working tree). Note that older versions of Git used to ignore removed files; use --no-all option if you want to add modified or new files but ignore removed ones.
For more details about the <pathspec> syntax, see the pathspec entry in the section called “gitglossary(7)”.
Interactively choose hunks of patch between the index and the work tree and add them to the index. This gives the user a chance to review the difference before adding modified contents to the index.
This effectively runs add --interactive, but bypasses the initial command menu and directly jumps to the patch subcommand. See Interactive mode for details.
Open the diff vs. the index in an editor and let the user edit it. After the editor was closed, adjust the hunk headers and apply the patch to the index.
The intent of this option is to pick and choose lines of the patch to apply, or even to modify the contents of lines to be staged. This can be quicker and more flexible than using the interactive hunk selector. However, it is easy to confuse oneself and create a patch that does not apply to the index. See EDITING PATCHES below.
Update the index just where it already has an entry matching <pathspec>. This removes as well as modifies index entries to match the working tree, but adds no new files.
If no <pathspec> is given when -u option is used, all tracked files in the entire working tree are updated (old versions of Git used to limit the update to the current directory and its subdirectories).
Update the index not only where the working tree has a file matching <pathspec> but also where the index already has an entry. This adds, modifies, and removes index entries to match the working tree.
If no <pathspec> is given when -A option is used, all files in the entire working tree are updated (old versions of Git used to limit the update to the current directory and its subdirectories).
Update the index by adding new files that are unknown to the index and files modified in the working tree, but ignore files that have been removed from the working tree. This option is a no-op when no <pathspec> is used.
This option is primarily to help users who are used to older versions of Git, whose git add <pathspec>... was a synonym for git add --no-all <pathspec>..., i.e. ignored removed files.
Adds content from all *.txt files under Documentation directory
and its subdirectories:
$ git add Documentation/\*.txt
Note that the asterisk * is quoted from the shell in this
example; this lets the command include the files from
subdirectories of Documentation/ directory.
Considers adding content from all git-*.sh scripts:
$ git add git-*.sh
Because this example lets the shell expand the asterisk (i.e. you are listing the files explicitly), it does not consider subdir/git-foo.sh.
When the command enters the interactive mode, it shows the output of the status subcommand, and then goes into its interactive command loop.
The command loop shows the list of subcommands available, and gives a prompt "What now> ". In general, when the prompt ends with a single >, you can pick only one of the choices given and type return, like this:
*** Commands ***
1: status 2: update 3: revert 4: add untracked
5: patch 6: diff 7: quit 8: help
What now> 1You also could say s or sta or status above as long as the choice is unique.
The main command loop has 6 subcommands (plus help and quit).
This shows the change between HEAD and index (i.e. what will be committed if you say git commit), and between index and working tree files (i.e. what you could stage further before git commit using git add) for each path. A sample output looks like this:
staged unstaged path
1: binary nothing foo.png
2: +403/-35 +1/-1 add-interactive.cIt shows that foo.png has differences from HEAD (but that is binary so line count cannot be shown) and there is no difference between indexed copy and the working tree version (if the working tree version were also different, binary would have been shown in place of nothing). The other file, add-interactive.c, has 403 lines added and 35 lines deleted if you commit what is in the index, but working tree file has further modifications (one addition and one deletion).
This shows the status information and issues an "Update>>" prompt. When the prompt ends with double >>, you can make more than one selection, concatenated with whitespace or comma. Also you can say ranges. E.g. "2-5 7,9" to choose 2,3,4,5,7,9 from the list. If the second number in a range is omitted, all remaining patches are taken. E.g. "7-" to choose 7,8,9 from the list. You can say * to choose everything.
What you chose are then highlighted with *, like this:
staged unstaged path 1: binary nothing foo.png * 2: +403/-35 +1/-1 add-interactive.c
To remove selection, prefix the input with - like this:
Update>> -2
After making the selection, answer with an empty line to stage the contents of working tree files for selected paths in the index.
This lets you choose one path out of a status like selection. After choosing the path, it presents the diff between the index and the working tree file and asks you if you want to stage the change of each hunk. You can select one of the following options and type return:
y - stage this hunk n - do not stage this hunk q - quit; do not stage this hunk or any of the remaining ones a - stage this hunk and all later hunks in the file d - do not stage this hunk or any of the later hunks in the file g - select a hunk to go to / - search for a hunk matching the given regex j - leave this hunk undecided, see next undecided hunk J - leave this hunk undecided, see next hunk k - leave this hunk undecided, see previous undecided hunk K - leave this hunk undecided, see previous hunk s - split the current hunk into smaller hunks e - manually edit the current hunk p - print the current hunk ? - print help
After deciding the fate for all hunks, if there is any hunk that was chosen, the index is updated with the selected hunks.
You can omit having to type return here, by setting the configuration variable interactive.singleKey to true.
Invoking git add -e or selecting e from the interactive hunk selector will open a patch in your editor; after the editor exits, the result is applied to the index. You are free to make arbitrary changes to the patch, but note that some changes may have confusing results, or even result in a patch that cannot be applied. If you want to abort the operation entirely (i.e., stage nothing new in the index), simply delete all lines of the patch. The list below describes some common things you may see in a patch, and which editing operations make sense on them.
There are also more complex operations that can be performed. But beware that because the patch is applied only to the index and not the working tree, the working tree will appear to "undo" the change in the index. For example, introducing a new line into the index that is in neither the HEAD nor the working tree will stage the new line for commit, but the line will appear to be reverted in the working tree.
Avoid using these constructs, or do so with extreme caution.
There are also several operations which should be avoided entirely, as they will make the patch impossible to apply:
Everything below this line in this section is selectively included from the the section called “git-config(1)” documentation. The content is the same as what's found there:
the section called “git-status(1)” the section called “git-rm(1)” the section called “git-reset(1)” the section called “git-mv(1)” the section called “git-commit(1)” the section called “git-update-index(1)”
Part of the the section called “git(1)” suite
git am [--signoff] [--keep] [--[no-]keep-cr] [--[no-]utf8] [--no-verify]
[--[no-]3way] [--interactive] [--committer-date-is-author-date]
[--ignore-date] [--ignore-space-change | --ignore-whitespace]
[--whitespace=<action>] [-C<n>] [-p<n>] [--directory=<dir>]
[--exclude=<path>] [--include=<path>] [--reject] [-q | --quiet]
[--[no-]scissors] [-S[<keyid>]] [--patch-format=<format>]
[--quoted-cr=<action>]
[--empty=(stop|drop|keep)]
[(<mbox> | <Maildir>)…]
git am (--continue | --skip | --abort | --quit | --retry | --show-current-patch[=(diff|raw)] | --allow-empty)
Splits mail messages in a mailbox into commit log messages, authorship information, and patches, and applies them to the current branch. You could think of it as a reverse operation of the section called “git-format-patch(1)” run on a branch with a straight history without merges.
How to handle an e-mail message lacking a patch:
Pass -u flag to git mailinfo (see the section called “git-mailinfo(1)”). The proposed commit log message taken from the e-mail is re-coded into UTF-8 encoding (configuration variable i18n.commitEncoding can be used to specify the project's preferred encoding if it is not UTF-8).
This was optional in prior versions of git, but now it is the default. You can use --no-utf8 to override this.
These flags are passed to the git apply (see the section called “git-apply(1)”) program that applies the patch.
Valid <action> for the --whitespace option are: nowarn, warn, fix, error, and error-all.
The commit author name is taken from the "From: " line of the message, and commit author date is taken from the "Date: " line of the message. The "Subject: " line is used as the title of the commit, after stripping common prefix "[PATCH <anything>]". The "Subject: " line is supposed to concisely describe what the commit is about in one line of text.
"From: ", "Date: ", and "Subject: " lines starting the body override the respective commit author name and title values taken from the headers.
The commit message is formed by the title taken from the "Subject: ", a blank line and the body of the message up to where the patch begins. Excess whitespace at the end of each line is automatically stripped.
The patch is expected to be inline, directly following the message. Any line that is of the form:
is taken as the beginning of a patch, and the commit log message is terminated before the first occurrence of such a line.
When initially invoking git am, you give it the names of the mailboxes to process. Upon seeing the first patch that does not apply, it aborts in the middle. You can recover from this in one of two ways:
The command refuses to process new mailboxes until the current operation is finished, so if you decide to start over from scratch, run git am --abort before running the command with mailbox names.
Before any patches are applied, ORIG_HEAD is set to the tip of the current branch. This is useful if you have problems with multiple commits, like running git am on the wrong branch or an error in the commits that is more easily fixed by changing the mailbox (e.g. errors in the "From:" lines).
This command can run applypatch-msg, pre-applypatch, and post-applypatch hooks. See the section called “githooks(5)” for more information.
Everything below this line in this section is selectively included from the the section called “git-config(1)” documentation. The content is the same as what's found there:
Part of the the section called “git(1)” suite
Annotates each line in the given file with information from the commit which introduced the line. Optionally annotates from a given revision.
The only difference between this command and the section called “git-blame(1)” is that they use slightly different output formats, and this command exists only for backward compatibility to support existing scripts, and provide a more familiar command name for people coming from other SCM systems.
Annotate only the line range given by <start>,<end>, or by the function name regex <funcname>. May be specified multiple times. Overlapping ranges are allowed.
<start> and <end> are optional. -L <start> or -L <start>, spans from <start> to end of file. -L ,<end> spans from start of file to <end>.
<start> and <end> can take one of these forms:
number
If <start> or <end> is a number, it specifies an absolute line number (lines count from 1).
/regex/
This form will use the first line matching the given POSIX regex. If <start> is a regex, it will search from the end of the previous -L range, if any, otherwise from the start of file. If <start> is ^/regex/, it will search from the start of file. If <end> is a regex, it will search starting at the line given by <start>.
+offset or -offset
This is only valid for <end> and will specify a number of lines before or after the line given by <start>.
If :<funcname> is given in place of <start> and <end>, it is a regular expression that denotes the range from the first funcname line that matches <funcname>, up to the next funcname line. :<funcname> searches from the end of the previous -L range, if any, otherwise from the start of file. ^:<funcname> searches from the start of file. The function names are determined in the same way as git diff works out patch hunk headers (see Defining a custom hunk-header in the section called “gitattributes(5)”).
Detect moved or copied lines within a file. When a commit moves or copies a block of lines (e.g. the original file has A and then B, and the commit changes it to B and then A), the traditional blame algorithm notices only half of the movement and typically blames the lines that were moved up (i.e. B) to the parent and assigns blame to the lines that were moved down (i.e. A) to the child commit. With this option, both groups of lines are blamed on the parent by running extra passes of inspection.
<num> is optional but it is the lower bound on the number of alphanumeric characters that Git must detect as moving/copying within a file for it to associate those lines with the parent commit. The default value is 20.
In addition to -M, detect lines moved or copied from other files that were modified in the same commit. This is useful when you reorganize your program and move code around across files. When this option is given twice, the command additionally looks for copies from other files in the commit that creates the file. When this option is given three times, the command additionally looks for copies from other files in any commit.
<num> is optional but it is the lower bound on the number of alphanumeric characters that Git must detect as moving/copying between files for it to associate those lines with the parent commit. And the default value is 40. If there are more than one -C options given, the <num> argument of the last -C will take effect.
Part of the the section called “git(1)” suite
git apply [--stat] [--numstat] [--summary] [--check]
[--index | --intent-to-add] [--3way] [--ours | --theirs | --union]
[--apply] [--no-add] [--build-fake-ancestor=<file>] [-R | --reverse]
[--allow-binary-replacement | --binary] [--reject] [-z]
[-p<n>] [-C<n>] [--inaccurate-eof] [--recount] [--cached]
[--ignore-space-change | --ignore-whitespace]
[--whitespace=(nowarn|warn|fix|error|error-all)]
[--exclude=<path>] [--include=<path>] [--directory=<root>]
[--verbose | --quiet] [--unsafe-paths] [--allow-empty] [<patch>…]
Reads the supplied diff output (i.e. "a patch") and applies it to files. When running from a subdirectory in a repository, patched paths outside the directory are ignored. With the --index option, the patch is also applied to the index, and with the --cached option, the patch is only applied to the index. Without these options, the command applies the patch only to files, and does not require them to be in a Git repository.
This command applies the patch but does not create a commit. Use the section called “git-am(1)” to create commits from patches generated by the section called “git-format-patch(1)” and/or received by email.
Newer git diff output has embedded index information for each blob to help identify the original version that the patch applies to. When this flag is given, and if the original versions of the blobs are available locally, builds a temporary index containing those blobs.
When a pure mode change is encountered (which has no index information), the information is read from the current index instead.
When --numstat has been given, do not munge pathnames, but use a NUL-terminated machine-readable format.
Without this option, pathnames with "unusual" characters are quoted as explained for the configuration variable core.quotePath (see the section called “git-config(1)”).
By default, git apply expects that the patch being applied is a unified diff with at least one line of context. This provides good safety measures, but breaks down when applying a diff generated with --unified=0. To bypass these checks use --unidiff-zero.
Note, for the reasons stated above, the usage of context-free patches is discouraged.
Apply changes to files matching the given path pattern. This can be useful when importing patchsets, where you want to include certain files or directories.
When --exclude and --include patterns are used, they are examined in the order they appear on the command line, and the first match determines if a patch to each path is used. A patch to a path that does not match any include/exclude pattern is used by default if there is no include pattern on the command line, and ignored if there is any include pattern.
When applying a patch, detect a new or modified line that has whitespace errors. What are considered whitespace errors is controlled by core.whitespace configuration. By default, trailing whitespaces (including lines that solely consist of whitespaces) and a space character that is immediately followed by a tab character inside the initial indent of the line are considered whitespace errors.
By default, the command outputs warning messages but applies the patch. When git-apply is used for statistics and not applying a patch, it defaults to nowarn.
You can use different <action> values to control this behavior:
Prepend <root> to all filenames. If a "-p" argument was also passed, it is applied before prepending the new root.
For example, a patch that talks about updating a/git-gui.sh to b/git-gui.sh can be applied to the file in the working tree modules/git-gui/git-gui.sh by running git apply --directory=modules/git-gui.
By default, a patch that affects outside the working area (either a Git controlled working tree, or the current working directory when "git apply" is used as a replacement of GNU patch) is rejected as a mistake (or a mischief).
When git apply is used as a "better GNU patch", the user can pass the --unsafe-paths option to override this safety check. This option has no effect when --index or --cached is in use.
Everything below this line in this section is selectively included from the the section called “git-config(1)” documentation. The content is the same as what's found there:
If the patch contains any changes to submodules then git apply treats these changes as follows.
If --index is specified (explicitly or implicitly), then the submodule commits must match the index exactly for the patch to apply. If any of the submodules are checked-out, then these check-outs are completely ignored, i.e., they are not required to be up to date or clean and they are not updated.
If --index is not specified, then the submodule commits in the patch are ignored and only the absence or presence of the corresponding subdirectory is checked and (if possible) updated.
Part of the the section called “git(1)” suite
git archimport [-h] [-v] [-o] [-a] [-f] [-T] [-D <depth>] [-t <tempdir>]
<archive>/<branch>[:<git-branch>]…
Imports a project from one or more GNU Arch repositories. It will follow branches and repositories within the namespaces defined by the <archive>/<branch> parameters supplied. If it cannot find the remote branch a merge comes from it will just import it as a regular commit. If it can find it, it will mark it as a merge whenever possible (see discussion below).
The script expects you to provide the key roots where it can start the import from an initial import or tag type of Arch commit. It will follow and import new branches within the provided roots.
It expects to be dealing with one project only. If it sees branches that have different roots, it will refuse to run. In that case, edit your <archive>/<branch> parameters to define clearly the scope of the import.
git archimport uses tla extensively in the background to access the Arch repository. Make sure you have a recent version of tla available in the path. tla must know about the repositories you pass to git archimport.
For the initial import, git archimport expects to find itself in an empty directory. To follow the development of a project that uses Arch, rerun git archimport with the same parameters as the initial import to perform incremental imports.
While git archimport will try to create sensible branch names for the archives that it imports, it is also possible to specify Git branch names manually. To do so, write a Git branch name after each <archive>/<branch> parameter, separated by a colon. This way, you can shorten the Arch branch names and convert Arch jargon to Git jargon, for example mapping a "PROJECT--devo--VERSION" branch to "master".
Associating multiple Arch branches to one Git branch is possible; the result will make the most sense only if no commits are made to the first branch, after the second branch is created. Still, this is useful to convert Arch repositories that had been rotated periodically.
Patch merge data from Arch is used to mark merges in Git as well. Git does not care much about tracking patches, and only considers a merge when a branch incorporates all the commits since the point they forked. The end result is that Git will have a good idea of how far branches have diverged. So the import process does lose some patch-trading metadata.
Fortunately, when you try and merge branches imported from Arch, Git will find a good merge base, and it has a good chance of identifying patches that have been traded out-of-sequence between the branches.
Part of the the section called “git(1)” suite
git archive [--format=<fmt>] [--list] [--prefix=<prefix>/] [<extra>]
[-o <file> | --output=<file>] [--worktree-attributes]
[--remote=<repo> [--exec=<git-upload-archive>]] <tree-ish>
[<path>…]
Creates an archive of the specified format containing the tree structure for the named tree, and writes it out to the standard output. If <prefix> is specified it is prepended to the filenames in the archive.
git archive behaves differently when given a tree ID as opposed to a commit ID or tag ID. When a tree ID is provided, the current time is used as the modification time of each file in the archive. On the other hand, when a commit ID or tag ID is provided, the commit time as recorded in the referenced commit object is used instead. Additionally the commit ID is stored in a global extended pax header if the tar format is used; it can be extracted using git get-tar-commit-id. In ZIP files it is stored as a file comment.
Add the specified contents to the archive. Can be repeated to add multiple files.
The <path> argument can start and end with a literal double-quote character; the contained file name is interpreted as a C-style string, i.e. the backslash is interpreted as escape character. The path must be quoted if it contains a colon, to avoid the colon from being misinterpreted as the separator between the path and the contents, or if the path begins or ends with a double-quote character.
The file mode is limited to a regular file, and the option may be subject to platform-dependent command-line limits. For non-trivial cases, write an untracked file and use --add-file instead.
Note that unlike --add-file the path created in the archive is not affected by the --prefix option, as a full <path> can be given as the value of the option.
This variable specifies a shell command through which the tar output generated by git archive should be piped. The command is executed using the shell with the generated tar file on its standard input, and should produce the final output on its standard output. Any compression-level options will be passed to the command (e.g., -9).
The tar.gz and tgz formats are defined automatically and use the magic command git archive gzip by default, which invokes an internal implementation of gzip.
Note that attributes are by default taken from the .gitattributes files in the tree that is being archived. If you want to tweak the way the output is generated after the fact (e.g. you committed without adding an appropriate export-ignore in its .gitattributes), adjust the checked out .gitattributes file as necessary and use --worktree-attributes option. Alternatively you can keep necessary attributes that should apply while archiving any tree in your $GIT_DIR/info/attributes file.
Part of the the section called “git(1)” suite
Blobless partial clones are created using git clone --filter=blob:none and then configure the local repository such that the Git client avoids downloading blob objects unless they are required for a local operation. This initially means that the clone and later fetches download reachable commits and trees but no blobs. Later operations that change the HEAD pointer, such as git checkout or git merge, may need to download missing blobs in order to complete their operation.
In the worst cases, commands that compute blob diffs, such as git blame, become very slow as they download the missing blobs in single-blob requests to satisfy the missing object as the Git command needs it. This leads to multiple download requests and no ability for the Git server to provide delta compression across those objects.
The git backfill command provides a way for the user to request that Git downloads the missing blobs (with optional filters) such that the missing blobs representing historical versions of files can be downloaded in batches. The backfill command attempts to optimize the request by grouping blobs that appear at the same path, hopefully leading to good delta compression in the packfile sent by the server.
In this way, git backfill provides a mechanism to break a large clone into smaller chunks. Starting with a blobless partial clone with git clone --filter=blob:none and then running git backfill in the local repository provides a way to download all reachable objects in several smaller network calls than downloading the entire repository at clone time.
By default, git backfill downloads all blobs reachable from the HEAD commit. This set can be restricted or expanded using various options.
THIS COMMAND IS EXPERIMENTAL. ITS BEHAVIOR MAY CHANGE IN THE FUTURE.
Part of the the section called “git(1)” suite
The command takes various subcommands, and different options depending on the subcommand:
git bisect start [--term-(bad|new)=<term-new> --term-(good|old)=<term-old>]
[--no-checkout] [--first-parent] [<bad> [<good>...]] [--] [<pathspec>...]
git bisect (bad|new|<term-new>) [<rev>]
git bisect (good|old|<term-old>) [<rev>...]
git bisect terms [--term-(good|old) | --term-(bad|new)]
git bisect skip [(<rev>|<range>)...]
git bisect reset [<commit>]
git bisect (visualize|view)
git bisect replay <logfile>
git bisect log
git bisect run <cmd> [<arg>...]
git bisect helpThis command uses a binary search algorithm to find which commit in your project's history introduced a bug. You use it by first telling it a "bad" commit that is known to contain the bug, and a "good" commit that is known to be before the bug was introduced. Then git bisect picks a commit between those two endpoints and asks you whether the selected commit is "good" or "bad". It continues narrowing down the range until it finds the exact commit that introduced the change.
In fact, git bisect can be used to find the commit that changed any property of your project; e.g., the commit that fixed a bug, or the commit that caused a benchmark's performance to improve. To support this more general usage, the terms "old" and "new" can be used in place of "good" and "bad", or you can choose your own terms. See section "Alternate terms" below for more information.
As an example, suppose you are trying to find the commit that broke a feature that was known to work in version v2.6.13-rc2 of your project. You start a bisect session as follows:
$ git bisect start $ git bisect bad # Current version is bad $ git bisect good v2.6.13-rc2 # v2.6.13-rc2 is known to be good
Once you have specified at least one bad and one good commit, git bisect selects a commit in the middle of that range of history, checks it out, and outputs something similar to the following:
Bisecting: 675 revisions left to test after this (roughly 10 steps)
You should now compile the checked-out version and test it. If that version works correctly, type
$ git bisect good
If that version is broken, type
$ git bisect bad
Then git bisect will respond with something like
Bisecting: 337 revisions left to test after this (roughly 9 steps)
Keep repeating the process: compile the tree, test it, and depending on whether it is good or bad run git bisect good or git bisect bad to ask for the next commit that needs testing.
Eventually there will be no more revisions left to inspect, and the command will print out a description of the first bad commit. The reference refs/bisect/bad will be left pointing at that commit.
After a bisect session, to clean up the bisection state and return to the original HEAD, issue the following command:
$ git bisect reset
By default, this will return your tree to the commit that was checked out before git bisect start. (A new git bisect start will also do that, as it cleans up the old bisection state.)
With an optional argument, you can return to a different commit instead:
$ git bisect reset <commit>
For example, git bisect reset bisect/bad will check out the first bad revision, while git bisect reset HEAD will leave you on the current bisection commit and avoid switching commits at all.
Sometimes you are not looking for the commit that introduced a breakage, but rather for a commit that caused a change between some other "old" state and "new" state. For example, you might be looking for the commit that introduced a particular fix. Or you might be looking for the first commit in which the source-code filenames were finally all converted to your company's naming standard. Or whatever.
In such cases it can be very confusing to use the terms "good" and "bad" to refer to "the state before the change" and "the state after the change". So instead, you can use the terms "old" and "new", respectively, in place of "good" and "bad". (But note that you cannot mix "good" and "bad" with "old" and "new" in a single session.)
In this more general usage, you provide git bisect with a "new" commit that has some property and an "old" commit that doesn't have that property. Each time git bisect checks out a commit, you test if that commit has the property. If it does, mark the commit as "new"; otherwise, mark it as "old". When the bisection is done, git bisect will report which commit introduced the property.
To use "old" and "new" instead of "good" and bad, you must run git bisect start without commits as argument and then run the following commands to add the commits:
git bisect old [<rev>]
to indicate that a commit was before the sought change, or
git bisect new [<rev>...]
to indicate that it was after.
To get a reminder of the currently used terms, use
git bisect terms
You can get just the old term with git bisect terms --term-old or git bisect terms --term-good; git bisect terms --term-new and git bisect terms --term-bad can be used to learn how to call the commits more recent than the sought change.
If you would like to use your own terms instead of "bad"/"good" or "new"/"old", you can choose any names you like (except existing bisect subcommands like reset, start, …) by starting the bisection using
git bisect start --term-old <term-old> --term-new <term-new>
For example, if you are looking for a commit that introduced a performance regression, you might use
git bisect start --term-old fast --term-new slow
Or if you are looking for the commit that fixed a bug, you might use
git bisect start --term-new fixed --term-old broken
Then, use git bisect <term-old> and git bisect <term-new> instead of git bisect good and git bisect bad to mark commits.
To see the currently remaining suspects in gitk, issue the following command during the bisection process (the subcommand view can be used as an alternative to visualize):
$ git bisect visualize
Git detects a graphical environment through various environment variables: DISPLAY, which is set in X Window System environments on Unix systems. SESSIONNAME, which is set under Cygwin in interactive desktop sessions. MSYSTEM, which is set under Msys2 and Git for Windows. SECURITYSESSIONID, which may be set on macOS in interactive desktop sessions.
If none of these environment variables is set, git log is used instead. You can also give command-line options such as -p and --stat.
$ git bisect visualize --stat
After having marked revisions as good or bad, issue the following command to show what has been done so far:
$ git bisect log
If you discover that you made a mistake in specifying the status of a revision, you can save the output of this command to a file, edit it to remove the incorrect entries, and then issue the following commands to return to a corrected state:
$ git bisect reset $ git bisect replay that-file
If, in the middle of a bisect session, you know that the suggested revision is not a good one to test (e.g. it fails to build and you know that the failure does not have anything to do with the bug you are chasing), you can manually select a nearby commit and test that one instead.
For example:
$ git bisect good/bad # previous round was good or bad.
Bisecting: 337 revisions left to test after this (roughly 9 steps)
$ git bisect visualize # oops, that is uninteresting.
$ git reset --hard HEAD~3 # try 3 revisions before what
# was suggestedThen compile and test the chosen revision, and afterwards mark the revision as good or bad in the usual manner.
Instead of choosing a nearby commit by yourself, you can ask Git to do it for you by issuing the command:
$ git bisect skip # Current version cannot be tested
However, if you skip a commit adjacent to the one you are looking for, Git will be unable to tell exactly which of those commits was the first bad one.
You can also skip a range of commits, instead of just one commit, using range notation. For example:
$ git bisect skip v2.5..v2.6
This tells the bisect process that no commit after v2.5, up to and including v2.6, should be tested.
Note that if you also want to skip the first commit of the range you would issue the command:
$ git bisect skip v2.5 v2.5..v2.6
This tells the bisect process that the commits between v2.5 and v2.6 (inclusive) should be skipped.
You can further cut down the number of trials, if you know what part of the tree is involved in the problem you are tracking down, by specifying pathspec parameters when issuing the bisect start command:
$ git bisect start -- arch/i386 include/asm-i386
If you know beforehand more than one good commit, you can narrow the bisect space down by specifying all of the good commits immediately after the bad commit when issuing the bisect start command:
$ git bisect start v2.6.20-rc6 v2.6.20-rc4 v2.6.20-rc1 --
# v2.6.20-rc6 is bad
# v2.6.20-rc4 and v2.6.20-rc1 are goodIf you have a script that can tell if the current source code is good or bad, you can bisect by issuing the command:
$ git bisect run my_script arguments
Note that the script (my_script in the above example) should exit with code 0 if the current source code is good/old, and exit with a code between 1 and 127 (inclusive), except 125, if the current source code is bad/new.
Any other exit code will abort the bisect process. It should be noted that a program that terminates via exit(-1) leaves $? = 255, (see the exit(3) manual page), as the value is chopped with & 0377.
The special exit code 125 should be used when the current source code cannot be tested. If the script exits with this code, the current revision will be skipped (see git bisect skip above). 125 was chosen as the highest sensible value to use for this purpose, because 126 and 127 are used by POSIX shells to signal specific error status (127 is for command not found, 126 is for command found but not executable--these details do not matter, as they are normal errors in the script, as far as bisect run is concerned).
You may often find that during a bisect session you want to have temporary modifications (e.g. s/#define DEBUG 0/#define DEBUG 1/ in a header file, or "revision that does not have this commit needs this patch applied to work around another problem this bisection is not interested in") applied to the revision being tested.
To cope with such a situation, after the inner git bisect finds the next revision to test, the script can apply the patch before compiling, run the real test, and afterwards decide if the revision (possibly with the needed patch) passed the test and then rewind the tree to the pristine state. Finally the script should exit with the status of the real test to let the git bisect run command loop determine the eventual outcome of the bisect session.
Do not checkout the new working tree at each iteration of the bisection process. Instead just update the reference named BISECT_HEAD to make it point to the commit that should be tested.
This option may be useful when the test you would perform in each step does not require a checked out tree.
If the repository is bare, --no-checkout is assumed.
Follow only the first parent commit upon seeing a merge commit.
In detecting regressions introduced through the merging of a branch, the merge commit will be identified as introduction of the bug and its ancestors will be ignored.
This option is particularly useful in avoiding false positives when a merged branch contained broken or non-buildable commits, but the merge itself was OK.
Automatically bisect a broken build between v1.2 and HEAD:
$ git bisect start HEAD v1.2 -- # HEAD is bad, v1.2 is good $ git bisect run make # "make" builds the app $ git bisect reset # quit the bisect session
Automatically bisect a test failure between origin and HEAD:
$ git bisect start HEAD origin -- # HEAD is bad, origin is good $ git bisect run make test # "make test" builds and tests $ git bisect reset # quit the bisect session
Automatically bisect a broken test case:
$ cat ~/test.sh #!/bin/sh make || exit 125 # this skips broken builds ~/check_test_case.sh # does the test case pass? $ git bisect start HEAD HEAD~10 -- # culprit is among the last 10 $ git bisect run ~/test.sh $ git bisect reset # quit the bisect session
Here we use a test.sh custom script. In this script, if make fails, we skip the current commit. check_test_case.sh should exit 0 if the test case passes, and exit 1 otherwise.
It is safer if both test.sh and check_test_case.sh are outside the repository to prevent interactions between the bisect, make and test processes and the scripts.
Automatically bisect with temporary modifications (hot-fix):
$ cat ~/test.sh
#!/bin/sh
# tweak the working tree by merging the hot-fix branch
# and then attempt a build
if git merge --no-commit --no-ff hot-fix &&
make
then
# run project specific test and report its status
~/check_test_case.sh
status=$?
else
# tell the caller this is untestable
status=125
fi
# undo the tweak to allow clean flipping to the next commit
git reset --hard
# return control
exit $statusThis applies modifications from a hot-fix branch before each test run, e.g. in case your build or test environment changed so that older revisions may need a fix which newer ones have already. (Make sure the hot-fix branch is based off a commit which is contained in all revisions which you are bisecting, so that the merge does not pull in too much, or use git cherry-pick instead of git merge.)
Automatically bisect a broken test case:
$ git bisect start HEAD HEAD~10 -- # culprit is among the last 10 $ git bisect run sh -c "make || exit 125; ~/check_test_case.sh" $ git bisect reset # quit the bisect session
This shows that you can do without a run script if you write the test on a single line.
Locate a good region of the object graph in a damaged repository
$ git bisect start HEAD <known-good-commit> [ <boundary-commit> ... ] --no-checkout
$ git bisect run sh -c '
GOOD=$(git for-each-ref "--format=%(objectname)" refs/bisect/good-*) &&
git rev-list --objects BISECT_HEAD --not $GOOD >tmp.$$ &&
git pack-objects --stdout >/dev/null <tmp.$$
rc=$?
rm -f tmp.$$
test $rc = 0'
$ git bisect reset # quit the bisect sessionIn this case, when git bisect run finishes, bisect/bad will refer to a commit that has at least one parent whose reachable graph is fully traversable in the sense required by git pack objects.
Look for a fix instead of a regression in the code
$ git bisect start $ git bisect new HEAD # current commit is marked as new $ git bisect old HEAD~10 # the tenth commit from now is marked as old
or:
$ git bisect start --term-old broken --term-new fixed $ git bisect fixed $ git bisect broken HEAD~10
Part of the the section called “git(1)” suite
git blame [-c] [-b] [-l] [--root] [-t] [-f] [-n] [-s] [-e] [-p] [-w] [--incremental]
[-L <range>] [-S <revs-file>] [-M] [-C] [-C] [-C] [--since=<date>]
[--ignore-rev <rev>] [--ignore-revs-file <file>]
[--color-lines] [--color-by-age] [--progress] [--abbrev=<n>]
[ --contents <file> ] [<rev> | --reverse <rev>..<rev>] [--] <file>
Annotates each line in the given file with information from the revision which last modified the line. Optionally, start annotating from the given revision.
When specified one or more times, -L restricts annotation to the requested lines.
The origin of lines is automatically followed across whole-file renames (currently there is no option to turn the rename-following off). To follow lines moved from one file to another, or to follow lines that were copied and pasted from another file, etc., see the -C and -M options.
The report does not tell you anything about lines which have been deleted or replaced; you need to use a tool such as git diff or the "pickaxe" interface briefly mentioned in the following paragraph.
Apart from supporting file annotation, Git also supports searching the development history for when a code snippet occurred in a change. This makes it possible to track when a code snippet was added to a file, moved or copied between files, and eventually deleted or replaced. It works by searching for a text string in the diff. A small example of the pickaxe interface that searches for blame_usage:
$ git log --pretty=oneline -S'blame_usage' 5040f17eba15504bad66b14a645bddd9b015ebb7 blame -S <ancestry-file> ea4c7f9bf69e781dd0cd88d2bccb2bf5cc15c9a7 git-blame: Make the output
Annotate only the line range given by <start>,<end>, or by the function name regex <funcname>. May be specified multiple times. Overlapping ranges are allowed.
<start> and <end> are optional. -L <start> or -L <start>, spans from <start> to end of file. -L ,<end> spans from start of file to <end>.
<start> and <end> can take one of these forms:
number
If <start> or <end> is a number, it specifies an absolute line number (lines count from 1).
/regex/
This form will use the first line matching the given POSIX regex. If <start> is a regex, it will search from the end of the previous -L range, if any, otherwise from the start of file. If <start> is ^/regex/, it will search from the start of file. If <end> is a regex, it will search starting at the line given by <start>.
+offset or -offset
This is only valid for <end> and will specify a number of lines before or after the line given by <start>.
If :<funcname> is given in place of <start> and <end>, it is a regular expression that denotes the range from the first funcname line that matches <funcname>, up to the next funcname line. :<funcname> searches from the end of the previous -L range, if any, otherwise from the start of file. ^:<funcname> searches from the start of file. The function names are determined in the same way as git diff works out patch hunk headers (see Defining a custom hunk-header in the section called “gitattributes(5)”).
Detect moved or copied lines within a file. When a commit moves or copies a block of lines (e.g. the original file has A and then B, and the commit changes it to B and then A), the traditional blame algorithm notices only half of the movement and typically blames the lines that were moved up (i.e. B) to the parent and assigns blame to the lines that were moved down (i.e. A) to the child commit. With this option, both groups of lines are blamed on the parent by running extra passes of inspection.
<num> is optional but it is the lower bound on the number of alphanumeric characters that Git must detect as moving/copying within a file for it to associate those lines with the parent commit. The default value is 20.
In addition to -M, detect lines moved or copied from other files that were modified in the same commit. This is useful when you reorganize your program and move code around across files. When this option is given twice, the command additionally looks for copies from other files in the commit that creates the file. When this option is given three times, the command additionally looks for copies from other files in any commit.
<num> is optional but it is the lower bound on the number of alphanumeric characters that Git must detect as moving/copying between files for it to associate those lines with the parent commit. And the default value is 40. If there are more than one -C options given, the <num> argument of the last -C will take effect.
When neither --porcelain nor --incremental option is specified, git blame will output annotation for each line with:
before the line contents.
In this format, each line is output after a header; the header at the minimum has the first line which has:
This header line is followed by the following information at least once for each commit:
The contents of the actual line are output after the above header, prefixed by a TAB. This is to allow adding more header elements later.
The porcelain format generally suppresses commit information that has already been seen. For example, two lines that are blamed to the same commit will both be shown, but the details for that commit will be shown only once. Information which is specific to individual lines will not be grouped together, like revs to be marked ignored or unblamable. This is more efficient, but may require more state be kept by the reader. The --line-porcelain option can be used to output full commit information for each line, allowing simpler (but less efficient) usage like:
# count the number of lines attributed to each author git blame --line-porcelain file | sed -n 's/^author //p' | sort | uniq -c | sort -rn
Unlike git blame and git annotate in older versions of git, the extent of the annotation can be limited to both line ranges and revision ranges. The -L option, which limits annotation to a range of lines, may be specified multiple times.
When you are interested in finding the origin for lines 40-60 for file foo, you can use the -L option like so (they mean the same thing -- both ask for 21 lines starting at line 40):
git blame -L 40,60 foo git blame -L 40,+21 foo
Also you can use a regular expression to specify the line range:
git blame -L '/^sub hello {/,/^}$/' foowhich limits the annotation to the body of the hello subroutine.
When you are not interested in changes older than version v2.6.18, or changes older than 3 weeks, you can use revision range specifiers similar to git rev-list:
git blame v2.6.18.. -- foo git blame --since=3.weeks -- foo
When revision range specifiers are used to limit the annotation, lines that have not changed since the range boundary (either the commit v2.6.18 or the most recent commit that is more than 3 weeks old in the above example) are blamed for that range boundary commit.
A particularly useful way is to see if an added file has lines created by copy-and-paste from existing files. Sometimes this indicates that the developer was being sloppy and did not refactor the code properly. You can first find the commit that introduced the file with:
git log --diff-filter=A --pretty=short -- foo
and then annotate the change between the commit and its parents, using commit^! notation:
git blame -C -C -f $commit^! -- foo
When called with --incremental option, the command outputs the result as it is built. The output generally will talk about lines touched by more recent commits first (i.e. the lines will be annotated out of order) and is meant to be used by interactive viewers.
The output format is similar to the Porcelain format, but it does not contain the actual lines from the file that is being annotated.
Each blame entry always starts with a line of:
<40-byte-hex-sha1> <sourceline> <resultline> <num-lines>
Line numbers count from 1.
Unlike the Porcelain format, the filename information is always given and terminates the entry:
"filename" <whitespace-quoted-filename-goes-here>
and thus it is really quite easy to parse for some line- and word-oriented parser (which should be quite natural for most scripting languages).
For people who do parsing: to make it more robust, just ignore any lines between the first and last one ("<sha1>" and "filename" lines) where you do not recognize the tag words (or care about that particular one) at the beginning of the "extended information" lines. That way, if there is ever added information (like the commit encoding or extended commit commentary), a blame viewer will not care.
Everything below this line in this section is selectively included from the the section called “git-config(1)” documentation. The content is the same as what's found there:
Part of the the section called “git(1)” suite
gitbranch[--color[=<when>] |--no-color] [--show-current]
[-v[--abbrev=<n> |--no-abbrev]]
[--column[=<options>] |--no-column] [--sort=<key>]
[--merged[<commit>]] [--no-merged[<commit>]]
[--contains[<commit>]] [--no-contains[<commit>]]
[--points-at<object>] [--format=<format>]
[(-r|--remotes) | (-a|--all)]
[--list] [<pattern>…]
gitbranch[--track[=(direct|inherit)] |--no-track] [-f]
[--recurse-submodules] <branch-name> [<start-point>]
gitbranch(--set-upstream-to=<upstream>|-u<upstream>) [<branch-name>]
gitbranch--unset-upstream[<branch-name>]
gitbranch(-m|-M) [<old-branch>] <new-branch>
gitbranch(-c|-C) [<old-branch>] <new-branch>
gitbranch(-d|-D) [-r] <branch-name>…
gitbranch--edit-description[<branch-name>]
If --list is given, or if there are no non-option arguments, existing branches are listed; the current branch will be highlighted in green and marked with an asterisk. Any branches checked out in linked worktrees will be highlighted in cyan and marked with a plus sign. Option -r causes the remote-tracking branches to be listed, and option -a shows both local and remote branches.
If a <pattern> is given, it is used as a shell wildcard to restrict the output to matching branches. If multiple patterns are given, a branch is shown if it matches any of the patterns.
Note that when providing a <pattern>, you must use --list; otherwise the command may be interpreted as branch creation.
With --contains, shows only the branches that contain the named commit (in other words, the branches whose tip commits are descendants of the named commit), --no-contains inverts it. With --merged, only branches merged into the named commit (i.e. the branches whose tip commits are reachable from the named commit) will be listed. With --no-merged only branches not merged into the named commit will be listed. If the <commit> argument is missing it defaults to HEAD (i.e. the tip of the current branch).
The command's second form creates a new branch head named <branch-name> which points to the current HEAD, or <start-point> if given. As a special case, for <start-point>, you may use <rev-A>...<rev-B> as a shortcut for the merge base of <rev-A> and <rev-B> if there is exactly one merge base. You can leave out at most one of <rev-A> and <rev-B>, in which case it defaults to HEAD.
Note that this will create the new branch, but it will not switch the working tree to it; use git switch <new-branch> to switch to the new branch.
When a local branch is started off a remote-tracking branch, Git sets up the branch (specifically the branch.<name>.remote and branch.<name>.merge configuration entries) so that git pull will appropriately merge from the remote-tracking branch. This behavior may be changed via the global branch.autoSetupMerge configuration flag. That setting can be overridden by using the --track and --no-track options, and changed later using git branch --set-upstream-to.
With a -m or -M option, <old-branch> will be renamed to <new-branch>. If <old-branch> had a corresponding reflog, it is renamed to match <new-branch>, and a reflog entry is created to remember the branch renaming. If <new-branch> exists, -M must be used to force the rename to happen.
The -c and -C options have the exact same semantics as -m and -M, except instead of the branch being renamed, it will be copied to a new name, along with its config and reflog.
With a -d or -D option, <branch-name> will be deleted. You may specify more than one branch for deletion. If the branch currently has a reflog then the reflog will also be deleted.
Use -r together with -d to delete remote-tracking branches. Note, that it only makes sense to delete remote-tracking branches if they no longer exist in the remote repository or if git fetch was configured not to fetch them again. See also the prune subcommand of the section called “git-remote(1)” for a way to clean up all obsolete remote-tracking branches.
Reset <branch-name> to <start-point>, even if <branch-name> exists already. Without -f, git branch refuses to change an existing branch. In combination with -d (or --delete), allow deleting the branch irrespective of its merged status, or whether it even points to a valid commit. In combination with -m (or --move), allow renaming the branch even if the new branch name already exists, the same applies for -c (or --copy).
Note that git branch -f <branch-name> [<start-point>], even with -f, refuses to change an existing branch <branch-name> that is checked out in another worktree linked to the same repository.
Display branch listing in columns. See configuration variable column.branch for option syntax. --column and --no-column without options are equivalent to always and never respectively.
This option is only applicable in non-verbose mode.
When creating a new branch, set up branch.<name>.remote and branch.<name>.merge configuration entries to set "upstream" tracking configuration for the new branch. This configuration will tell git to show the relationship between the two branches in git status and git branch -v. Furthermore, it directs git pull without arguments to pull from the upstream when the new branch is checked out.
The exact upstream branch is chosen depending on the optional argument: -t, --track, or --track=direct means to use the start-point branch itself as the upstream; --track=inherit means to copy the upstream configuration of the start-point branch.
The branch.autoSetupMerge configuration variable specifies how git switch, git checkout and git branch should behave when neither --track nor --no-track are specified:
The default option, true, behaves as though --track=direct were given whenever the start-point is a remote-tracking branch. false behaves as if --no-track were given. always behaves as though --track=direct were given. inherit behaves as though --track=inherit were given. simple behaves as though --track=direct were given only when the <start-point> is a remote-tracking branch and the new branch has the same name as the remote branch.
See the section called “git-pull(1)” and the section called “git-config(1)” for additional discussion on how the branch.<name>.remote and branch.<name>.merge options are used.
THIS OPTION IS EXPERIMENTAL! Cause the current command to recurse into submodules if submodule.propagateBranches is enabled. See submodule.propagateBranches in the section called “git-config(1)”. Currently, only branch creation is supported.
When used in branch creation, a new branch <branch-name> will be created in the superproject and all of the submodules in the superproject's <start-point>. In submodules, the branch will point to the submodule commit in the superproject's <start-point> but the branch's tracking information will be set up based on the submodule's branches and remotes e.g. git branch --recurse-submodules topic origin/main will create the submodule branch "topic" that points to the submodule commit in the superproject's "origin/main", but tracks the submodule's "origin/main".
pager.branch is only respected when listing branches, i.e., when --list is used or implied. The default is to use a pager. See the section called “git-config(1)”.
Everything above this line in this section isn't included from the the section called “git-config(1)” documentation. The content that follows is the same as what's found there:
Tells git branch, git switch and git checkout to set up new branches so that the section called “git-pull(1)” will appropriately merge from the starting point branch. Note that even if this option is not set, this behavior can be chosen per-branch using the --track and --no-track options. This option defaults to true. The valid settings are:
When a new branch is created with git branch, git switch or git checkout that tracks another branch, this variable tells Git to set up pull to rebase instead of merge (see branch.<name>.rebase). The valid settings are:
See branch.autoSetupMerge for details on how to set up a branch to track another branch. This option defaults to never.
When true, rebase the branch <name> on top of the fetched branch, instead of merging the default branch from the default remote when git pull is run. See pull.rebase for doing this in a non branch-specific manner.
When merges (or just m), pass the --rebase-merges option to git rebase so that the local merge commits are included in the rebase (see the section called “git-rebase(1)” for details).
When the value is interactive (or just i), the rebase is run in interactive mode.
NOTE: this is a possibly dangerous operation; do not use it unless you understand the implications (see the section called “git-rebase(1)” for details).
$ git clone git://git.kernel.org/pub/scm/.../linux-2.6 my2.6 $ cd my2.6 $ git branch my2.6.14 v2.6.14$ git switch my2.6.14
$ git clone git://git.kernel.org/.../git.git my.git $ cd my.git $ git branch -d -r origin/todo origin/html origin/man$ git branch -D test
Delete the remote-tracking branches "todo", "html" and "man". The next git fetch or git pull will create them again unless you configure them not to. See the section called “git-fetch(1)”. | |
Delete the "test" branch even if the "master" branch (or whichever branch is currently checked out) does not have all commits from the test branch. |
$ git branch -r -l '<remote>/<pattern>'$ git for-each-ref 'refs/remotes/<remote>/<pattern>'
Using -a would conflate <remote> with any local branches you happen to have been prefixed with the same <remote> pattern. | |
for-each-ref can take a wide range of options. See the section called “git-for-each-ref(1)” |
Patterns will normally need quoting.
If you are creating a branch that you want to switch to immediately, it is easier to use the git switch command with its -c option to do the same thing with a single command.
The options --contains, --no-contains, --merged and --no-merged serve four related but different purposes:
When combining multiple --contains and --no-contains filters, only references that contain at least one of the --contains commits and contain none of the --no-contains commits are shown.
When combining multiple --merged and --no-merged filters, only references that are reachable from at least one of the --merged commits and from none of the --no-merged commits are shown.
the section called “git-check-ref-format(1)”, the section called “git-fetch(1)”, the section called “git-remote(1)”, "Understanding history: What is a branch?" in the Git User's Manual.
Part of the the section called “git(1)” suite
git bugreport [(-o | --output-directory) <path>]
[(-s | --suffix) <format> | --no-suffix]
[--diagnose[=<mode>]]
Collects information about the user's machine, Git client, and repository state, in addition to a form requesting information about the behavior the user observed, and stores it in a single text file which the user can then share, for example to the Git mailing list, in order to report an observed bug.
The following information is requested from the user:
The following information is captured automatically:
Additional information may be gathered into a separate zip archive using the --diagnose option, and can be attached alongside the bugreport document to provide additional context to readers.
This tool is invoked via the typical Git setup process, which means that in some cases, it might not be able to launch - for example, if a relevant config file is unreadable. In this kind of scenario, it may be helpful to manually gather the kind of information listed above when manually asking for help.
Create a zip archive of supplemental information about the user's machine, Git client, and repository state. The archive is written to the same output directory as the bug report and is named git-diagnostics-<formatted-suffix>.
Without mode specified, the diagnostic archive will contain the default set of statistics reported by git diagnose. An optional mode value may be specified to change which information is included in the archive. See the section called “git-diagnose(1)” for the list of valid values for mode and details about their usage.
Part of the the section called “git(1)” suite
git bundle create [-q | --quiet | --progress]
[--version=<version>] <file> <git-rev-list-args>
git bundle verify [-q | --quiet] <file>
git bundle list-heads <file> [<refname>…]
git bundle unbundle [--progress] <file> [<refname>…]
Create, unpack, and manipulate "bundle" files. Bundles are used for the "offline" transfer of Git objects without an active "server" sitting on the other side of the network connection.
They can be used to create both incremental and full backups of a repository (see the "full backup" example in "EXAMPLES"), and to relay the state of the references in one repository to another (see the second example).
Git commands that fetch or otherwise "read" via protocols such as ssh:// and https:// can also operate on bundle files. It is possible the section called “git-clone(1)” a new repository from a bundle, to use the section called “git-fetch(1)” to fetch from one, and to list the references contained within it with the section called “git-ls-remote(1)”. There's no corresponding "write" support, i.e. a git push into a bundle is not supported.
Bundles are .pack files (see the section called “git-pack-objects(1)”) with a header indicating what references are contained within the bundle.
Like the packed archive format itself bundles can either be self-contained, or be created using exclusions. See the "OBJECT PREREQUISITES" section below.
Bundles created using revision exclusions are "thin packs" created using the --thin option to the section called “git-pack-objects(1)”, and unbundled using the --fix-thin option to the section called “git-index-pack(1)”.
There is no option to create a "thick pack" when using revision exclusions, and users should not be concerned about the difference. By using "thin packs", bundles created using exclusions are smaller in size. That they're "thin" under the hood is merely noted here as a curiosity, and as a reference to other documentation.
See the section called “gitformat-bundle(5)” for more details and the discussion of "thin pack" in the section called “gitformat-pack(5)” for further details.
Revisions must be accompanied by reference names to be packaged in a bundle. Alternatively --all can be used to package all refs.
More than one reference may be packaged, and more than one set of prerequisite objects can be specified. The objects packaged are those not contained in the union of the prerequisites.
The git bundle create command resolves the reference names for you using the same rules as git rev-parse --abbrev-ref=loose. Each prerequisite can be specified explicitly (e.g. ^master~10), or implicitly (e.g. master~10..master, --since=10.days.ago master).
All of these simple cases are OK (assuming we have a "master" and "next" branch):
$ git bundle create master.bundle master $ echo master | git bundle create master.bundle --stdin $ git bundle create master-and-next.bundle master next $ (echo master; echo next) | git bundle create master-and-next.bundle --stdin
And so are these (and the same but omitted --stdin examples):
$ git bundle create recent-master.bundle master~10..master $ git bundle create recent-updates.bundle master~10..master next~5..next
A revision name or a range whose right-hand-side cannot be resolved to a reference is not accepted:
$ git bundle create HEAD.bundle $(git rev-parse HEAD) fatal: Refusing to create empty bundle. $ git bundle create master-yesterday.bundle master~10..master~5 fatal: Refusing to create empty bundle.
When creating bundles it is possible to create a self-contained bundle that can be unbundled in a repository with no common history, as well as providing negative revisions to exclude objects needed in the earlier parts of the history.
Feeding a revision such as new to git bundle create will create a bundle file that contains all the objects reachable from the revision new. That bundle can be unbundled in any repository to obtain a full history that leads to the revision new:
$ git bundle create full.bundle new
A revision range such as old..new will produce a bundle file that will require the revision old (and any objects reachable from it) to exist for the bundle to be "unbundle"-able:
$ git bundle create full.bundle old..new
A self-contained bundle without any prerequisites can be extracted into anywhere, even into an empty repository, or be cloned from (i.e., new, but not old..new).
It is okay to err on the side of caution, causing the bundle file to contain objects already in the destination, as these are ignored when unpacking at the destination.
If you want to provide the same set of refs that a clone directly from the source repository would get, use --branches --tags for the <git-rev-list-args>.
The git bundle verify command can be used to check whether your recipient repository has the required prerequisite commits for a bundle.
We'll discuss two cases:
First let's consider a full backup of the repository. The following command will take a full backup of the repository in the sense that all refs are included in the bundle:
$ git bundle create backup.bundle --all
But note again that this is only for the refs, i.e. you will only include refs and commits reachable from those refs. You will not include other local state, such as the contents of the index, working tree, the stash, per-repository configuration, hooks, etc.
You can later recover that repository by using for example the section called “git-clone(1)”:
$ git clone backup.bundle <new directory>
For the next example, assume you want to transfer the history from a repository R1 on machine A to another repository R2 on machine B. For whatever reason, direct connection between A and B is not allowed, but we can move data from A to B via some mechanism (CD, email, etc.). We want to update R2 with development made on the branch master in R1.
To bootstrap the process, you can first create a bundle that does not have any prerequisites. You can use a tag to remember up to what commit you last processed, in order to make it easy to later update the other repository with an incremental bundle:
machineA$ cd R1 machineA$ git bundle create file.bundle master machineA$ git tag -f lastR2bundle master
Then you transfer file.bundle to the target machine B. Because this bundle does not require any existing object to be extracted, you can create a new repository on machine B by cloning from it:
machineB$ git clone -b master /home/me/tmp/file.bundle R2
This will define a remote called "origin" in the resulting repository that lets you fetch and pull from the bundle. The $GIT_DIR/config file in R2 will have an entry like this:
[remote "origin"]
url = /home/me/tmp/file.bundle
fetch = refs/heads/*:refs/remotes/origin/*To update the resulting mine.git repository, you can fetch or pull after replacing the bundle stored at /home/me/tmp/file.bundle with incremental updates.
After working some more in the original repository, you can create an incremental bundle to update the other repository:
machineA$ cd R1 machineA$ git bundle create file.bundle lastR2bundle..master machineA$ git tag -f lastR2bundle master
You then transfer the bundle to the other machine to replace /home/me/tmp/file.bundle, and pull from it.
machineB$ cd R2 machineB$ git pull
If you know up to what commit the intended recipient repository should have the necessary objects, you can use that knowledge to specify the prerequisites, giving a cut-off point to limit the revisions and objects that go in the resulting bundle. The previous example used the lastR2bundle tag for this purpose, but you can use any other options that you would give to the the section called “git-log(1)” command. Here are more examples:
You can use a tag that is present in both:
$ git bundle create mybundle v1.0.0..master
You can use a prerequisite based on time:
$ git bundle create mybundle --since=10.days master
You can use the number of commits:
$ git bundle create mybundle -10 master
You can run git-bundle verify to see if you can extract from a bundle that was created with a prerequisite:
$ git bundle verify mybundle
This will list what commits you must have in order to extract from the bundle and will error out if you do not have them.
A bundle from a recipient repository's point of view is just like a regular repository which it fetches or pulls from. You can, for example, map references when fetching:
$ git fetch mybundle master:localRef
You can also see what references it offers:
$ git ls-remote mybundle
A naive way to make a full backup of a repository is to use something to the effect of cp -r <repo> <destination>. This is discouraged since the repository could be written to during the copy operation. In turn some files at <destination> could be corrupted.
This is why it is recommended to use Git tooling for making repository backups, either with this command or with e.g. the section called “git-clone(1)”. But keep in mind that these tools will not help you backup state other than refs and commits. In other words they will not help you backup contents of the index, working tree, the stash, per-repository configuration, hooks, etc.
See also the section called “gitfaq(7)”, section "TRANSFERS" for a discussion of the problems associated with file syncing across systems.
Part of the the section called “git(1)” suite
git cat-file <type> <object>
git cat-file (-e | -p | -t | -s) <object>
git cat-file (--textconv | --filters)
[<rev>:<path|tree-ish> | --path=<path|tree-ish> <rev>]
git cat-file (--batch | --batch-check | --batch-command) [--batch-all-objects]
[--buffer] [--follow-symlinks] [--unordered]
[--textconv | --filters] [-Z]
Output the contents or other properties such as size, type or delta information of one or more objects.
This command can operate in two modes, depending on whether an option from the --batch family is specified.
In non-batch mode, the command provides information on an object named on the command line.
In batch mode, arguments are read from standard input.
Omit objects from the list of printed objects. This can only be used in combination with one of the batched modes. Excluded objects that have been explicitly requested via any of the batch modes that read objects via standard input (--batch, --batch-check) will be reported as "filtered". Excluded objects in --batch-all-objects mode will not be printed at all. The <filter-spec> may be one of the following:
The form --filter=blob:none omits all blobs.
The form --filter=blob:limit=<n>[kmg] omits blobs of size at least n bytes or units. n may be zero. The suffixes k, m, and g can be used to name units in KiB, MiB, or GiB. For example, blob:limit=1k is the same as blob:limit=1024.
The form --filter=object:type=(tag|commit|tree|blob) omits all objects which are not of the requested type.
Print object information and contents for each object provided on stdin. May not be combined with any other options or arguments except --textconv, --filters, or --use-mailmap.
Print object information for each object provided on stdin. May not be combined with any other options or arguments except --textconv, --filters or --use-mailmap.
Enter a command mode that reads commands and arguments from stdin. May only be combined with --buffer, --textconv, --use-mailmap or --filters.
--batch-command recognizes the following commands:
With --batch or --batch-check, follow symlinks inside the repository when requesting objects with extended SHA-1 expressions of the form tree-ish:path-in-tree. Instead of providing output about the link itself, provide output about the linked-to object. If a symlink points outside the tree-ish (e.g. a link to /foo or a root-level link to ../foo), the portion of the link which is outside the tree will be printed.
This option does not (currently) work correctly when an object in the index is specified (e.g. :link instead of HEAD:link) rather than one in the tree.
This option cannot (currently) be used unless --batch or --batch-check is used.
For example, consider a git repository containing:
f: a file containing "hello\n" link: a symlink to f dir/link: a symlink to ../f plink: a symlink to ../f alink: a symlink to /etc/passwd
For a regular file f, echo HEAD:f | git cat-file --batch would print
ce013625030ba8dba906f756967f9e9ca394464a blob 6
And echo HEAD:link | git cat-file --batch --follow-symlinks would print the same thing, as would HEAD:dir/link, as they both point at HEAD:f.
Without --follow-symlinks, these would print data about the symlink itself. In the case of HEAD:link, you would see
4d1ae35ba2c8ec712fa2a379db44ad639ca277bd blob 1
Both plink and alink point outside the tree, so they would respectively print:
symlink 4 ../f
symlink 11 /etc/passwd
If -t is specified, one of the <type>.
If -s is specified, the size of the <object> in bytes.
If -e is specified, no output, unless the <object> is malformed.
If -p is specified, the contents of <object> are pretty-printed.
If <type> is specified, the raw (though uncompressed) contents of the <object> will be returned.
If --batch or --batch-check is given, cat-file will read objects from stdin, one per line, and print information about them in the same order as they have been read. By default, the whole line is considered as an object, as if it were fed to the section called “git-rev-parse(1)”.
When --batch-command is given, cat-file will read commands from stdin, one per line, and print information based on the command given. With --batch-command, the info command followed by an object will print information about the object the same way --batch-check would, and the contents command followed by an object prints contents in the same way --batch would.
You can specify the information shown for each object by using a custom <format>. The <format> is copied literally to stdout for each object, with placeholders of the form %(atom) expanded, followed by a newline. The available atoms are:
If no format is specified, the default format is %(objectname) %(objecttype) %(objectsize).
If --batch is specified, or if --batch-command is used with the contents command, the object information is followed by the object contents (consisting of %(objectsize) bytes), followed by a newline.
For example, --batch without a custom format would produce:
<oid> SP <type> SP <size> LF <contents> LF
Whereas --batch-check='%(objectname) %(objecttype)' would produce:
<oid> SP <type> LF
If a name is specified on stdin that cannot be resolved to an object in the repository, then cat-file will ignore any custom format and print:
<object> SP missing LF
If a name is specified on stdin that is filtered out via --filter=, then cat-file will ignore any custom format and print:
<object> SP excluded LF
If a name is specified that might refer to more than one object (an ambiguous short sha), then cat-file will ignore any custom format and print:
<object> SP ambiguous LF
If --follow-symlinks is used, and a symlink in the repository points outside the repository, then cat-file will ignore any custom format and print:
symlink SP <size> LF <symlink> LF
The symlink will either be absolute (beginning with a /), or relative to the tree root. For instance, if dir/link points to ../../foo, then <symlink> will be ../foo. <size> is the size of the symlink in bytes.
If --follow-symlinks is used, the following error messages will be displayed:
<object> SP missing LF
is printed when the initial symlink requested does not exist.
dangling SP <size> LF <object> LF
is printed when the initial symlink exists, but something that it (transitive-of) points to does not.
loop SP <size> LF <object> LF
is printed for symlink loops (or any symlinks that require more than 40 link resolutions to resolve).
notdir SP <size> LF <object> LF
is printed when, during symlink resolution, a file is used as a directory name.
Alternatively, when -Z is passed, the line feeds in any of the above examples are replaced with NUL terminators. This ensures that output will be parsable if the output itself would contain a linefeed and is thus recommended for scripting purposes.
Note that the sizes of objects on disk are reported accurately, but care should be taken in drawing conclusions about which refs or objects are responsible for disk usage. The size of a packed non-delta object may be much larger than the size of objects which delta against it, but the choice of which object is the base and which is the delta is arbitrary and is subject to change during a repack.
Note also that multiple copies of an object may be present in the object database; in this case, it is undefined which copy's size or delta base will be reported.
Part of the the section called “git(1)” suite
git check-attr [--source <tree-ish>] [-a | --all | <attr>…] [--] <pathname>…
git check-attr --stdin [-z] [--source <tree-ish>] [-a | --all | <attr>…]
For every pathname, this command will list if each attribute is unspecified, set, or unset as a gitattribute on that pathname.
If none of --stdin, --all, or -- is used, the first argument will be treated as an attribute and the rest of the arguments as pathnames.
The output is of the form: <path> COLON SP <attribute> COLON SP <info> LF
unless -z is in effect, in which case NUL is used as delimiter: <path> NUL <attribute> NUL <info> NUL
<path> is the path of a file being queried, <attribute> is an attribute being queried, and <info> can be either:
Buffering happens as documented under the GIT_FLUSH option in the section called “git(1)”. The caller is responsible for avoiding deadlocks caused by overfilling an input buffer or reading from an empty output buffer.
In the examples, the following .gitattributes file is used:
*.java diff=java -crlf myAttr NoMyAttr.java !myAttr README caveat=unspecified
Listing a single attribute:
$ git check-attr diff org/example/MyClass.java org/example/MyClass.java: diff: java
Listing multiple attributes for a file:
$ git check-attr crlf diff myAttr -- org/example/MyClass.java org/example/MyClass.java: crlf: unset org/example/MyClass.java: diff: java org/example/MyClass.java: myAttr: set
Listing all attributes for a file:
$ git check-attr --all -- org/example/MyClass.java org/example/MyClass.java: diff: java org/example/MyClass.java: myAttr: set
Listing an attribute for multiple files:
$ git check-attr myAttr -- org/example/MyClass.java org/example/NoMyAttr.java org/example/MyClass.java: myAttr: set org/example/NoMyAttr.java: myAttr: unspecified
Not all values are equally unambiguous:
$ git check-attr caveat README README: caveat: unspecified
Part of the the section called “git(1)” suite
For each pathname given via the command-line or from a file via --stdin, check whether the file is excluded by .gitignore (or other input files to the exclude mechanism) and output the path if it is excluded.
By default, tracked files are not shown at all since they are not subject to exclude rules; but see --no-index.
Instead of printing the paths that are excluded, for each path that matches an exclude pattern, print the exclude pattern together with the path. (Matching an exclude pattern usually means the path is excluded, but if the pattern begins with "!" then it is a negated pattern and matching it means the path is NOT excluded.)
For precedence rules within and between exclude sources, see the section called “gitignore(5)”.
By default, any of the given pathnames which match an ignore pattern will be output, one per line. If no pattern matches a given path, nothing will be output for that path; this means that path will not be ignored.
If --verbose is specified, the output is a series of lines of the form:
<source> <COLON> <linenum> <COLON> <pattern> <HT> <pathname>
<pathname> is the path of a file being queried, <pattern> is the matching pattern, <source> is the pattern's source file, and <linenum> is the line number of the pattern within that source. If the pattern contained a "!" prefix or "/" suffix, it will be preserved in the output. <source> will be an absolute path when referring to the file configured by core.excludesFile, or relative to the repository root when referring to .git/info/exclude or a per-directory exclude file.
If -z is specified, the pathnames in the output are delimited by the null character; if --verbose is also specified then null characters are also used instead of colons and hard tabs:
<source> <NULL> <linenum> <NULL> <pattern> <NULL> <pathname> <NULL>
If -n or --non-matching are specified, non-matching pathnames will also be output, in which case all fields in each output record except for <pathname> will be empty. This can be useful when running non-interactively, so that files can be incrementally streamed to STDIN of a long-running check-ignore process, and for each of these files, STDOUT will indicate whether that file matched a pattern or not. (Without this option, it would be impossible to tell whether the absence of output for a given file meant that it didn't match any pattern, or that the output hadn't been generated yet.)
Buffering happens as documented under the GIT_FLUSH option in the section called “git(1)”. The caller is responsible for avoiding deadlocks caused by overfilling an input buffer or reading from an empty output buffer.
the section called “gitignore(5)” the section called “git-config(1)” the section called “git-ls-files(1)”
Part of the the section called “git(1)” suite
For each Name <user@host>, <user@host>, or user@host from the command-line or standard input (when using --stdin), look up the person's canonical name and email address (see "Mapping Authors" below). If found, print them; otherwise print the input as-is.
For each contact, a single line is output, terminated by a newline. If the name is provided or known to the mailmap, Name <user@host> is printed; otherwise only <user@host> is printed.
See mailmap.file and mailmap.blob in the section called “git-config(1)” for how to specify a custom .mailmap target file or object.
Part of the the section called “git(1)” suite
git check-ref-format [--normalize]
[--[no-]allow-onelevel] [--refspec-pattern]
<refname>
git check-ref-format --branch <branchname-shorthand>
Checks if a given refname is acceptable, and exits with a non-zero status if it is not.
A reference is used in Git to specify branches and tags. A branch head is stored in the refs/heads hierarchy, while a tag is stored in the refs/tags hierarchy of the ref namespace (typically in $GIT_DIR/refs/heads and $GIT_DIR/refs/tags directories or, as entries in file $GIT_DIR/packed-refs if refs are packed by git gc).
Git imposes the following rules on how references are named:
These rules make it easy for shell script based tools to parse reference names, pathname expansion by the shell when a reference name is used unquoted (by mistake), and also avoid ambiguities in certain reference name expressions (see the section called “gitrevisions(7)”):
With the --branch option, the command takes a name and checks if it can be used as a valid branch name (e.g. when creating a new branch). But be cautious when using the previous checkout syntax that may refer to a detached HEAD state. The rule git check-ref-format --branch $name implements may be stricter than what git check-ref-format refs/heads/$name says (e.g. a dash may appear at the beginning of a ref component, but it is explicitly forbidden at the beginning of a branch name). When run with the --branch option in a repository, the input is first expanded for the previous checkout syntax @{-n}. For example, @{-1} is a way to refer the last thing that was checked out using "git switch" or "git checkout" operation. This option should be used by porcelains to accept this syntax anywhere a branch name is expected, so they can act as if you typed the branch name. As an exception note that, the previous checkout operation might result in a commit object name when the N-th last thing checked out was not a branch.
Print the name of the previous thing checked out:
$ git check-ref-format --branch @{-1}Determine the reference name to use for a new branch:
$ ref=$(git check-ref-format --normalize "refs/heads/$newbranch")||
{ echo "we do not like '$newbranch' as a branch name." >&2 ; exit 1 ; }Part of the the section called “git(1)” suite
git checkout-index [-u] [-q] [-a] [-f] [-n] [--prefix=<string>]
[--stage=<number>|all]
[--temp]
[--ignore-skip-worktree-bits]
[-z] [--stdin]
[--] [<file>…]
Copies all listed files from the index to the working directory (not overwriting existing files).
The order of the flags used to matter, but not anymore.
Just doing git checkout-index does nothing. You probably meant git checkout-index -a. And if you want to force it, you want git checkout-index -f -a.
Intuitiveness is not the goal here. Repeatability is. The reason for the "no arguments means no work" behavior is that from scripts you are supposed to be able to do:
$ find . -name '*.h' -print0 | xargs -0 git checkout-index -f --
which will force all existing *.h files to be replaced with their cached copies. If an empty command line implied "all", then this would force-refresh everything in the index, which was not the point. But since git checkout-index accepts --stdin it would be faster to use:
$ find . -name '*.h' -print0 | git checkout-index -f -z --stdin
The -- is just a good idea when you know the rest will be filenames; it will prevent problems with a filename of, for example, -a. Using -- is probably a good policy in scripts.
When --temp is used (or implied by --stage=all) git checkout-index will create a temporary file for each index entry being checked out. The index will not be updated with stat information. These options can be useful if the caller needs all stages of all unmerged entries so that the unmerged files can be processed by an external merge tool.
A listing will be written to stdout providing the association of temporary file names to tracked path names. The listing format has two variations:
tempname TAB path RS
The first format is what gets used when --stage is omitted or is not --stage=all. The field tempname is the temporary file name holding the file content and path is the tracked path name in the index. Only the requested entries are output.
stage1temp SP stage2temp SP stage3tmp TAB path RS
The second format is what gets used when --stage=all. The three stage temporary fields (stage1temp, stage2temp, stage3temp) list the name of the temporary file if there is a stage entry in the index or . if there is no stage entry. Paths which only have a stage 0 entry will always be omitted from the output.
In both formats RS (the record separator) is newline by default but will be the null byte if -z was passed on the command line. The temporary file names are always safe strings; they will never contain directory separators or whitespace characters. The path field is always relative to the current directory and the temporary file names are always relative to the top level directory.
If the object being copied out to a temporary file is a symbolic link the content of the link will be written to a normal file. It is up to the end-user or the Porcelain to make use of this information.
$ git checkout-index -n -f -a && git update-index --ignore-missing --refresh
The prefix ability basically makes it trivial to use git checkout-index as an "export as tree" function. Just read the desired tree into the index, and do:
$ git checkout-index --prefix=git-export-dir/ -a
git checkout-index will "export" the index into the specified directory.
The final "/" is important. The exported name is literally just prefixed with the specified string. Contrast this with the following example.
$ git checkout-index --prefix=.merged- Makefile
This will check out the currently cached copy of Makefile into the file .merged-Makefile.
Part of the the section called “git(1)” suite
gitcheckout[-q] [-f] [-m] [<branch>]
gitcheckout[-q] [-f] [-m]--detach[<branch>]
gitcheckout[-q] [-f] [-m] [--detach] <commit>
gitcheckout[-q] [-f] [-m] [[-b|-B|--orphan] <new-branch>] [<start-point>]
gitcheckout[-f] <tree-ish> [--] <pathspec>…
gitcheckout[-f] <tree-ish>--pathspec-from-file=<file> [--pathspec-file-nul]
gitcheckout[-f|--ours|--theirs|-m|--conflict=<style>] [--] <pathspec>…
gitcheckout[-f|--ours|--theirs|-m|--conflict=<style>]--pathspec-from-file=<file> [--pathspec-file-nul]
gitcheckout(-p|--patch) [<tree-ish>] [--] [<pathspec>…]
Updates files in the working tree to match the version in the index or the specified tree. If no pathspec was given, git checkout will also update HEAD to set the specified branch as the current branch.
To prepare for working on <branch>, switch to it by updating the index and the files in the working tree, and by pointing HEAD at the branch. Local modifications to the files in the working tree are kept, so that they can be committed to the <branch>.
If <branch> is not found but there does exist a tracking branch in exactly one remote (call it <remote>) with a matching name and --no-guess is not specified, treat as equivalent to
$ git checkout -b <branch> --track <remote>/<branch>
You could omit <branch>, in which case the command degenerates to "check out the current branch", which is a glorified no-op with rather expensive side-effects to show only the tracking information, if it exists, for the current branch.
Specifying -b causes a new branch to be created as if the section called “git-branch(1)” were called and then checked out. In this case you can use the --track or --no-track options, which will be passed to git branch. As a convenience, --track without -b implies branch creation; see the description of --track below.
If -B is given, <new-branch> is created if it doesn't exist; otherwise, it is reset. This is the transactional equivalent of
$ git branch -f <branch> [<start-point>] $ git checkout <branch>
that is to say, the branch is not reset/created unless "git checkout" is successful (e.g., when the branch is in use in another worktree, not just the current branch stays the same, but the branch is not reset to the start-point, either).
Prepare to work on top of <commit>, by detaching HEAD at it (see "DETACHED HEAD" section), and updating the index and the files in the working tree. Local modifications to the files in the working tree are kept, so that the resulting working tree will be the state recorded in the commit plus the local modifications.
When the <commit> argument is a branch name, the --detach option can be used to detach HEAD at the tip of the branch (git checkout <branch> would check out that branch without detaching HEAD).
Omitting <branch> detaches HEAD at the tip of the current branch.
Overwrite the contents of the files that match the pathspec. When the <tree-ish> (most often a commit) is not given, overwrite working tree with the contents in the index. When the <tree-ish> is given, overwrite both the index and the working tree with the contents at the <tree-ish>.
The index may contain unmerged entries because of a previous failed merge. By default, if you try to check out such an entry from the index, the checkout operation will fail and nothing will be checked out. Using -f will ignore these unmerged entries. The contents from a specific side of the merge can be checked out of the index by using --ours or --theirs. With -m, changes made to the working tree file can be discarded to re-create the original conflicted merge result.
When switching branches, proceed even if the index or the working tree differs from HEAD, and even if there are untracked files in the way. This is used to throw away local changes and any untracked files or directories that are in the way.
When checking out paths from the index, do not fail upon unmerged entries; instead, unmerged entries are ignored.
When checking out paths from the index, check out stage #2 (ours) or #3 (theirs) for unmerged paths.
Note that during git rebase and git pull --rebase, ours and theirs may appear swapped; --ours gives the version from the branch the changes are rebased onto, while --theirs gives the version from the branch that holds your work that is being rebased.
This is because rebase is used in a workflow that treats the history at the remote as the shared canonical one, and treats the work done on the branch you are rebasing as the third-party work to be integrated, and you are temporarily assuming the role of the keeper of the canonical history during the rebase. As the keeper of the canonical history, you need to view the history from the remote as ours (i.e. "our shared canonical history"), while what you did on your side branch as theirs (i.e. "one contributor's work on top of it").
When creating a new branch, set up "upstream" configuration. See --track in the section called “git-branch(1)” for details.
If no -b option is given, the name of the new branch will be derived from the remote-tracking branch, by looking at the local part of the refspec configured for the corresponding remote, and then stripping the initial part up to the "*". This would tell us to use hack as the local branch when branching off of origin/hack (or remotes/origin/hack, or even refs/remotes/origin/hack). If the given name has no slash, or the above guessing results in an empty name, the guessing is aborted. You can explicitly give a name with -b in such a case.
If <branch> is not found but there does exist a tracking branch in exactly one remote (call it <remote>) with a matching name, treat as equivalent to
$ git checkout -b <branch> --track <remote>/<branch>
If the branch exists in multiple remotes and one of them is named by the checkout.defaultRemote configuration variable, we'll use that one for the purposes of disambiguation, even if the <branch> isn't unique across all remotes. Set it to e.g. checkout.defaultRemote=origin to always checkout remote branches from there if <branch> is ambiguous but exists on the origin remote. See also checkout.defaultRemote in the section called “git-config(1)”.
--guess is the default behavior. Use --no-guess to disable it.
The default behavior can be set via the checkout.guess configuration variable.
Create a new unborn branch, named <new-branch>, started from <start-point> and switch to it. The first commit made on this new branch will have no parents and it will be the root of a new history totally disconnected from all the other branches and commits.
The index and the working tree are adjusted as if you had previously run git checkout <start-point>. This allows you to start a new history that records a set of paths similar to <start-point> by easily running git commit -a to make the root commit.
This can be useful when you want to publish the tree from a commit without exposing its full history. You might want to do this to publish an open source branch of a project whose current tree is "clean", but whose full history contains proprietary or otherwise encumbered bits of code.
If you want to start a disconnected history that records a set of paths that is totally different from the one of <start-point>, then you should clear the index and the working tree right after creating the orphan branch by running git rm -rf . from the top level of the working tree. Afterwards you will be ready to prepare your new files, repopulating the working tree, by copying them from elsewhere, extracting a tarball, etc.
When switching branches, if you have local modifications to one or more files that are different between the current branch and the branch to which you are switching, the command refuses to switch branches in order to preserve your modifications in context. However, with this option, a three-way merge between the current branch, your working tree contents, and the new branch is done, and you will be on the new branch.
When a merge conflict happens, the index entries for conflicting paths are left unmerged, and you need to resolve the conflicts and mark the resolved paths with git add (or git rm if the merge should result in deletion of the path).
When checking out paths from the index, this option lets you recreate the conflicted merge in the specified paths. This option cannot be used when checking out paths from a tree-ish.
When switching branches with --merge, staged changes may be lost.
Interactively select hunks in the difference between the <tree-ish> (or the index, if unspecified) and the working tree. The chosen hunks are then applied in reverse to the working tree (and if a <tree-ish> was specified, the index).
This means that you can use git checkout -p to selectively discard edits from your current working tree. See the "Interactive Mode" section of the section called “git-add(1)” to learn how to operate the --patch mode.
Note that this option uses the no overlay mode by default (see also --overlay), and currently doesn't support overlay mode.
Branch to checkout; if it refers to a branch (i.e., a name that, when prepended with "refs/heads/", is a valid ref), then that branch is checked out. Otherwise, if it refers to a valid commit, your HEAD becomes "detached" and you are no longer on any branch (see below for details).
You can use the @{-N} syntax to refer to the N-th last branch/commit checked out using "git checkout" operation. You may also specify - which is synonymous to @{-1}.
As a special case, you may use <rev-a>...<rev-b> as a shortcut for the merge base of <rev-a> and <rev-b> if there is exactly one merge base. You can leave out at most one of <rev-a> and <rev-b>, in which case it defaults to HEAD.
The name of a commit at which to start the new branch; see the section called “git-branch(1)” for details. Defaults to HEAD.
As a special case, you may use <rev-a>...<rev-b> as a shortcut for the merge base of <rev-a> and <rev-b> if there is exactly one merge base. You can leave out at most one of <rev-a> and <rev-b>, in which case it defaults to HEAD.
Tree to checkout from (when paths are given). If not specified, the index will be used.
As a special case, you may use <rev-a>...<rev-b> as a shortcut for the merge base of <rev-a> and <rev-b> if there is exactly one merge base. You can leave out at most one of <rev-a> and <rev-b>, in which case it defaults to HEAD.
Limits the paths affected by the operation.
For more details, see the pathspec entry in the section called “gitglossary(7)”.
HEAD normally refers to a named branch (e.g. master). Meanwhile, each branch refers to a specific commit. Let's look at a repo with three commits, one of them tagged, and with branch master checked out:
HEAD (refers to branch 'master')
|
v
a---b---c branch 'master' (refers to commit 'c')
^
|
tag 'v2.0' (refers to commit 'b')When a commit is created in this state, the branch is updated to refer to the new commit. Specifically, git commit creates a new commit d, whose parent is commit c, and then updates branch master to refer to new commit d. HEAD still refers to branch master and so indirectly now refers to commit d:
$ edit; git add; git commit
HEAD (refers to branch 'master')
|
v
a---b---c---d branch 'master' (refers to commit 'd')
^
|
tag 'v2.0' (refers to commit 'b')It is sometimes useful to be able to checkout a commit that is not at the tip of any named branch, or even to create a new commit that is not referenced by a named branch. Let's look at what happens when we checkout commit b (here we show two ways this may be done):
$ git checkout v2.0 # or
$ git checkout master^^
HEAD (refers to commit 'b')
|
v
a---b---c---d branch 'master' (refers to commit 'd')
^
|
tag 'v2.0' (refers to commit 'b')Notice that regardless of which checkout command we use, HEAD now refers directly to commit b. This is known as being in detached HEAD state. It means simply that HEAD refers to a specific commit, as opposed to referring to a named branch. Let's see what happens when we create a commit:
$ edit; git add; git commit
HEAD (refers to commit 'e')
|
v
e
/
a---b---c---d branch 'master' (refers to commit 'd')
^
|
tag 'v2.0' (refers to commit 'b')There is now a new commit e, but it is referenced only by HEAD. We can of course add yet another commit in this state:
$ edit; git add; git commit
HEAD (refers to commit 'f')
|
v
e---f
/
a---b---c---d branch 'master' (refers to commit 'd')
^
|
tag 'v2.0' (refers to commit 'b')In fact, we can perform all the normal Git operations. But, let's look at what happens when we then checkout master:
$ git checkout master
HEAD (refers to branch 'master')
e---f |
/ v
a---b---c---d branch 'master' (refers to commit 'd')
^
|
tag 'v2.0' (refers to commit 'b')It is important to realize that at this point nothing refers to commit f. Eventually commit f (and by extension commit e) will be deleted by the routine Git garbage collection process, unless we create a reference before that happens. If we have not yet moved away from commit f, any of these will create a reference to it:
$ git checkout -b foo # or "git switch -c foo"$ git branch foo
$ git tag foo
creates a new branch foo, which refers to commit f, and then updates HEAD to refer to branch foo. In other words, we'll no longer be in detached HEAD state after this command. | |
similarly creates a new branch foo, which refers to commit f, but leaves HEAD detached. | |
creates a new tag foo, which refers to commit f, leaving HEAD detached. |
If we have moved away from commit f, then we must first recover its object name (typically by using git reflog), and then we can create a reference to it. For example, to see the last two commits to which HEAD referred, we can use either of these commands:
$ git reflog -2 HEAD # or $ git log -g -2 HEAD
When there is only one argument given and it is not -- (e.g. git checkout abc), and when the argument is both a valid <tree-ish> (e.g. a branch abc exists) and a valid <pathspec> (e.g. a file or a directory whose name is "abc" exists), Git would usually ask you to disambiguate. Because checking out a branch is so common an operation, however, git checkout abc takes "abc" as a <tree-ish> in such a situation. Use git checkout -- <pathspec> if you want to checkout these paths out of the index.
The following sequence checks out the master branch, reverts the Makefile to two revisions back, deletes hello.c by mistake, and gets it back from the index.
$ git checkout master$ git checkout master~2 Makefile
$ rm -f hello.c $ git checkout hello.c
If you want to check out all C source files out of the index, you can say
$ git checkout -- '*.c'
Note the quotes around *.c. The file hello.c will also be checked out, even though it is no longer in the working tree, because the file globbing is used to match entries in the index (not in the working tree by the shell).
If you have an unfortunate branch that is named hello.c, this step would be confused as an instruction to switch to that branch. You should instead write:
$ git checkout -- hello.c
After working in the wrong branch, switching to the correct branch would be done using:
$ git checkout mytopic
However, your "wrong" branch and correct mytopic branch may differ in files that you have modified locally, in which case the above checkout would fail like this:
$ git checkout mytopic error: You have local changes to 'frotz'; not switching branches.
You can give the -m flag to the command, which would try a three-way merge:
$ git checkout -m mytopic Auto-merging frotz
After this three-way merge, the local modifications are not registered in your index file, so git diff would show you what changes you made since the tip of the new branch.
When a merge conflict happens during switching branches with the -m option, you would see something like this:
$ git checkout -m mytopic Auto-merging frotz ERROR: Merge conflict in frotz fatal: merge program failed
At this point, git diff shows the changes cleanly merged as in the previous example, as well as the changes in the conflicted files. Edit and resolve the conflict and mark it resolved with git add as usual:
$ edit frotz $ git add frotz
Everything below this line in this section is selectively included from the the section called “git-config(1)” documentation. The content is the same as what's found there:
When you run git checkout <something> or git switch <something> and only have one remote, it may implicitly fall back on checking out and tracking e.g. origin/<something>. This stops working as soon as you have more than one remote with a <something> reference. This setting allows for setting the name of a preferred remote that should always win when it comes to disambiguation. The typical use-case is to set this to origin.
Currently this is used by the section called “git-switch(1)” and the section called “git-checkout(1)” when git checkout <something> or git switch <something> will checkout the <something> branch on another remote, and by the section called “git-worktree(1)” when git worktree add refers to a remote branch. This setting might be used for other checkout-like commands or functionality in the future.
The number of parallel workers to use when updating the working tree. The default is one, i.e. sequential execution. If set to a value less than one, Git will use as many workers as the number of logical cores available. This setting and checkout.thresholdForParallelism affect all commands that perform checkout. E.g. checkout, clone, reset, sparse-checkout, etc.
Parallel checkout usually delivers better performance for repositories located on SSDs or over NFS. For repositories on spinning disks and/or machines with a small number of cores, the default sequential checkout often performs better. The size and compression level of a repository might also influence how well the parallel version performs.
Part of the the section called “git(1)” suite
git cherry-pick [--edit] [-n] [-m <parent-number>] [-s] [-x] [--ff]
[-S[<keyid>]] <commit>…
git cherry-pick (--continue | --skip | --abort | --quit)
Given one or more existing commits, apply the change each one introduces, recording a new commit for each. This requires your working tree to be clean (no modifications from the HEAD commit).
When it is not obvious how to apply a change, the following happens:
See the section called “git-merge(1)” for some hints on resolving such conflicts.
Usually the command automatically creates a sequence of commits. This flag applies the changes necessary to cherry-pick each named commit to your working tree and the index, without making any commit. In addition, when this option is used, your index does not have to match the HEAD commit. The cherry-pick is done against the beginning state of your index.
This is useful when cherry-picking more than one commits' effect to your index in a row.
How to handle commits being cherry-picked that are redundant with changes already in the current history.
Note that --empty=drop and --empty=stop only specify how to handle a commit that was not initially empty, but rather became empty due to a previous commit. Commits that were initially empty will still cause the cherry-pick to fail unless one of --empty=keep or --allow-empty are specified.
The following sequence attempts to backport a patch, bails out because the code the patch applies to has changed too much, and then tries again, this time exercising more care about matching up context lines.
$ git cherry-pick topic^$ git diff
$ git cherry-pick --abort
$ git cherry-pick -Xpatience topic^
apply the change that would be shown by git show topic^. In this example, the patch does not apply cleanly, so information about the conflict is written to the index and working tree and no new commit results. | |
summarize changes to be reconciled | |
cancel the cherry-pick. In other words, return to the pre-cherry-pick state, preserving any local modifications you had in the working tree. | |
try to apply the change introduced by topic^ again, spending extra time to avoid mistakes based on incorrectly matching context lines. |
Part of the the section called “git(1)” suite
Determine whether there are commits in <head>..<upstream> that are equivalent to those in the range <limit>..<head>.
The equivalence test is based on the diff, after removing whitespace and line numbers. git-cherry therefore detects when commits have been "copied" by means of the section called “git-cherry-pick(1)”, the section called “git-am(1)” or the section called “git-rebase(1)”.
Outputs the SHA1 of every commit in <limit>..<head>, prefixed with - for commits that have an equivalent in <upstream>, and + for commits that do not.
git-cherry is frequently used in patch-based workflows (see the section called “gitworkflows(7)”) to determine if a series of patches has been applied by the upstream maintainer. In such a workflow you might create and send a topic branch like this:
$ git checkout -b topic origin/master # work and create some commits $ git format-patch origin/master $ git send-email ... 00*
Later, you can see whether your changes have been applied by saying (still on topic):
$ git fetch # update your notion of origin/master $ git cherry -v
In a situation where topic consisted of three commits, and the maintainer applied two of them, the situation might look like:
$ git log --graph --oneline --decorate --boundary origin/master...topic * 7654321 (origin/master) upstream tip commit [... snip some other commits ...] * cccc111 cherry-pick of C * aaaa111 cherry-pick of A [... snip a lot more that has happened ...] | * cccc000 (topic) commit C | * bbbb000 commit B | * aaaa000 commit A |/ o 1234567 branch point
In such cases, git-cherry shows a concise summary of what has yet to be applied:
$ git cherry origin/master topic - cccc000... commit C + bbbb000... commit B - aaaa000... commit A
Here, we see that the commits A and C (marked with -) can be dropped from your topic branch when you rebase it on top of origin/master, while the commit B (marked with +) still needs to be kept so that it will be sent to be applied to origin/master.
The optional <limit> is useful in cases where your topic is based on other work that is not in upstream. Expanding on the previous example, this might look like:
$ git log --graph --oneline --decorate --boundary origin/master...topic * 7654321 (origin/master) upstream tip commit [... snip some other commits ...] * cccc111 cherry-pick of C * aaaa111 cherry-pick of A [... snip a lot more that has happened ...] | * cccc000 (topic) commit C | * bbbb000 commit B | * aaaa000 commit A | * 0000fff (base) unpublished stuff F [... snip ...] | * 0000aaa unpublished stuff A |/ o 1234567 merge-base between upstream and topic
By specifying base as the limit, you can avoid listing commits between base and topic:
$ git cherry origin/master topic base - cccc000... commit C + bbbb000... commit B - aaaa000... commit A
Part of the the section called “git(1)” suite
A Tcl/Tk based graphical interface to review modified files, stage them into the index, enter a commit message and record the new commit onto the current branch. This interface is an alternative to the less interactive git commit program.
git citool is actually a standard alias for git gui citool. See the section called “git-gui(1)” for more details.
Part of the the section called “git(1)” suite
Cleans the working tree by recursively removing files that are not under version control, starting from the current directory.
Normally, only files unknown to Git are removed, but if the -x option is specified, ignored files are also removed. This can, for example, be useful to remove all build products.
If any optional <pathspec>... arguments are given, only those paths that match the pathspec are affected.
When the command enters the interactive mode, it shows the files and directories to be cleaned, and goes into its interactive command loop.
The command loop shows the list of subcommands available, and gives a prompt "What now> ". In general, when the prompt ends with a single >, you can pick only one of the choices given and type return, like this:
*** Commands ***
1: clean 2: filter by pattern 3: select by numbers
4: ask each 5: quit 6: help
What now> 1You also could say c or clean above as long as the choice is unique.
The main command loop has 6 subcommands.
Everything below this line in this section is selectively included from the the section called “git-config(1)” documentation. The content is the same as what's found there:
Part of the the section called “git(1)” suite
gitclone[--template=<template-directory>]
[-l] [-s] [--no-hardlinks] [-q] [-n] [--bare] [--mirror]
[-o<name>] [-b<name>] [-u<upload-pack>] [--reference<repository>]
[--dissociate] [--separate-git-dir<git-dir>]
[--depth<depth>] [--[no-]single-branch] [--[no-]tags]
[--recurse-submodules[=<pathspec>]] [--[no-]shallow-submodules]
[--[no-]remote-submodules] [--jobs<n>] [--sparse] [--[no-]reject-shallow]
[--filter=<filter-spec>] [--also-filter-submodules]] [--] <repository>
[<directory>]
Clones a repository into a newly created directory, creates remote-tracking branches for each branch in the cloned repository (visible using git branch --remotes), and creates and checks out an initial branch that is forked from the cloned repository's currently active branch.
After the clone, a plain git fetch without arguments will update all the remote-tracking branches, and a git pull without arguments will in addition merge the remote master branch into the current master branch, if any (this is untrue when --single-branch is given; see below).
This default configuration is achieved by creating references to the remote branch heads under refs/remotes/origin and by initializing remote.origin.url and remote.origin.fetch configuration variables.
When the repository to clone from is on a local machine, this flag bypasses the normal "Git aware" transport mechanism and clones the repository by making a copy of HEAD and everything under objects and refs directories. The files under .git/objects/ directory are hardlinked to save space when possible.
If the repository is specified as a local path (e.g., /path/to/repo), this is the default, and --local is essentially a no-op. If the repository is specified as a URL, then this flag is ignored (and we never use the local optimizations). Specifying --no-local will override the default when /path/to/repo is given, using the regular Git transport instead.
If the repository's $GIT_DIR/objects has symbolic links or is a symbolic link, the clone will fail. This is a security measure to prevent the unintentional copying of files by dereferencing the symbolic links.
This option does not work with repositories owned by other users for security reasons, and --no-local must be specified for the clone to succeed.
NOTE: this operation can race with concurrent modification to the source repository, similar to running cp -r <src> <dst> while modifying <src>.
When the repository to clone is on the local machine, instead of using hard links, automatically setup .git/objects/info/alternates to share the objects with the source repository. The resulting repository starts out without any object of its own.
NOTE: this is a possibly dangerous operation; do not use it unless you understand what it does. If you clone your repository using this option and then delete branches (or use any other Git command that makes any existing commit unreferenced) in the source repository, some objects may become unreferenced (or dangling). These objects may be removed by normal Git operations (such as git commit) which automatically call git maintenance run --auto. (See the section called “git-maintenance(1)”.) If these objects are removed and were referenced by the cloned repository, then the cloned repository will become corrupt.
Note that running git repack without the --local option in a repository cloned with --shared will copy objects from the source repository into a pack in the cloned repository, removing the disk space savings of clone --shared. It is safe, however, to run git gc, which uses the --local option by default.
If you want to break the dependency of a repository cloned with --shared on its source repository, you can simply run git repack -a to copy all objects from the source repository into a pack in the cloned repository.
If the reference <repository> is on the local machine, automatically setup .git/objects/info/alternates to obtain objects from the reference <repository>. Using an already existing repository as an alternate will require fewer objects to be copied from the repository being cloned, reducing network and local storage costs. When using the --reference-if-able, a non existing directory is skipped with a warning instead of aborting the clone.
NOTE: see the NOTE for the --shared option, and also the --dissociate option.
--server-option=<option> is given from the command
line, the values of configuration variable remote.<name>.serverOption
are used instead.
Set a configuration variable in the newly-created repository; this takes effect immediately after the repository is initialized, but before the remote history is fetched or any files checked out. The <key> is in the same format as expected by the section called “git-config(1)” (e.g., core.eol=true). If multiple values are given for the same key, each value will be written to the config file. This makes it safe, for example, to add additional fetch refspecs to the origin remote.
Due to limitations of the current implementation, some configuration variables do not take effect until after the initial fetch and checkout. Configuration variables known to not take effect are: remote.<name>.mirror and remote.<name>.tagOpt. Use the corresponding --mirror and --no-tags options instead.
Control whether or not tags will be cloned. When --no-tags is given, the option will be become permanent by setting the remote.<remote>.tagOpt=--no-tags configuration. This ensures that future git pull and git fetch won't follow any tags. Subsequent explicit tag fetches will still work (see the section called “git-fetch(1)”).
By default, tags are cloned and passing --tags is thus typically a no-op, unless it cancels out a previous --no-tags.
Can be used in conjunction with --single-branch to clone and maintain a branch with no references other than a single cloned branch. This is useful e.g. to maintain minimal clones of the default branch of some repository for search indexing.
After the clone is created, initialize and clone submodules within based on the provided <pathspec>. If no =<pathspec> is provided, all submodules are initialized and cloned. This option can be given multiple times for pathspecs consisting of multiple entries. The resulting clone has submodule.active set to the provided pathspec, or "." (meaning all submodules) if no pathspec is provided.
Submodules are initialized and cloned using their default settings. This is equivalent to running git submodule update --init --recursive <pathspec> immediately after the clone is finished. This option is ignored if the cloned repository does not have a worktree/checkout (i.e. if any of --no-checkout/-n, --bare, or --mirror is given)
Specify the given ref storage format for the repository. The valid values are:
In general, URLs contain information about the transport protocol, the address of the remote server, and the path to the repository. Depending on the transport protocol, some of this information may be absent.
Git supports ssh, git, http, and https protocols (in addition, ftp and ftps can be used for fetching, but this is inefficient and deprecated; do not use them).
The native transport (i.e. git:// URL) does no authentication and should be used with caution on unsecured networks.
The following syntaxes may be used with them:
An alternative scp-like syntax may also be used with the ssh protocol:
This syntax is only recognized if there are no slashes before the first colon. This helps differentiate a local path that contains a colon. For example the local path foo:bar could be specified as an absolute path or ./foo:bar to avoid being misinterpreted as an ssh url.
The ssh and git protocols additionally support ~<username> expansion:
For local repositories, also supported by Git natively, the following syntaxes may be used:
These two syntaxes are mostly equivalent, except the former implies --local option.
git clone, git fetch and git pull, but not git push, will also accept a suitable bundle file. See the section called “git-bundle(1)”.
When Git doesn't know how to handle a certain transport protocol, it attempts to use the remote-<transport> remote helper, if one exists. To explicitly request a remote helper, the following syntax may be used:
where <address> may be a path, a server and path, or an arbitrary URL-like string recognized by the specific remote helper being invoked. See the section called “gitremote-helpers(7)” for details.
If there are a large number of similarly-named remote repositories and you want to use a different format for them (such that the URLs you use will be rewritten into URLs that work), you can create a configuration section of the form:
[url "<actual-url-base>"]
insteadOf = <other-url-base>
For example, with this:
[url "git://git.host.xz/"]
insteadOf = host.xz:/path/to/
insteadOf = work:a URL like "work:repo.git" or like "host.xz:/path/to/repo.git" will be rewritten in any context that takes a URL to be "git://git.host.xz/repo.git".
If you want to rewrite URLs for push only, you can create a configuration section of the form:
[url "<actual-url-base>"]
pushInsteadOf = <other-url-base>
For example, with this:
[url "ssh://example.org/"]
pushInsteadOf = git://example.org/a URL like "git://example.org/path/to/repo.git" will be rewritten to "ssh://example.org/path/to/repo.git" for pushes, but pulls will still use the original URL.
Clone from upstream:
$ git clone git://git.kernel.org/pub/scm/.../linux.git my-linux $ cd my-linux $ make
Make a local clone that borrows from the current directory, without checking things out:
$ git clone -l -s -n . ../copy $ cd ../copy $ git show-branch
Clone from upstream while borrowing from an existing local directory:
$ git clone --reference /git/linux.git \
git://git.kernel.org/pub/scm/.../linux.git \
my-linux
$ cd my-linuxCreate a bare repository to publish your changes to the public:
$ git clone --bare -l /home/proj/.git /pub/scm/proj.git
Clone a local repository from a different user:
$ git clone --no-local /home/otheruser/proj.git /pub/scm/proj.git
Everything below this line in this section is selectively included from the the section called “git-config(1)” documentation. The content is the same as what's found there:
Part of the the section called “git(1)” suite
git column [--command=<name>] [--[raw-]mode=<mode>] [--width=<width>]
[--indent=<string>] [--nl=<string>] [--padding=<n>]
This command formats the lines of its standard input into a table with multiple columns. Each input line occupies one cell of the table. It is used internally by other git commands to format output into columns.
Format data by columns:
$ seq 1 24 | git column --mode=column --padding=5 1 4 7 10 13 16 19 22 2 5 8 11 14 17 20 23 3 6 9 12 15 18 21 24
Format data by rows:
$ seq 1 21 | git column --mode=row --padding=5 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
List some tags in a table with unequal column widths:
$ git tag --list 'v2.4.*' --column=row,dense v2.4.0 v2.4.0-rc0 v2.4.0-rc1 v2.4.0-rc2 v2.4.0-rc3 v2.4.1 v2.4.10 v2.4.11 v2.4.12 v2.4.2 v2.4.3 v2.4.4 v2.4.5 v2.4.6 v2.4.7 v2.4.8 v2.4.9
Everything below this line in this section is selectively included from the the section called “git-config(1)” documentation. The content is the same as what's found there:
Specify whether supported commands should output in columns. This variable consists of a list of tokens separated by spaces or commas:
These options control when the feature should be enabled (defaults to never):
These options control layout (defaults to column). Setting any of these implies always if none of always, never, or auto are specified.
Finally, these options can be combined with a layout option (defaults to nodense):
Part of the the section called “git(1)” suite
git commit-graph verify [--object-dir <dir>] [--shallow] [--[no-]progress]
git commit-graph write [--object-dir <dir>] [--append]
[--split[=<strategy>]] [--reachable | --stdin-packs | --stdin-commits]
[--changed-paths] [--[no-]max-new-filters <n>] [--[no-]progress]
<split-options>
Write a commit-graph file based on the commits found in packfiles. If the config option core.commitGraph is disabled, then this command will output a warning, then return success without writing a commit-graph file.
With the --stdin-packs option, generate the new commit graph by walking objects only in the specified pack-indexes. (Cannot be combined with --stdin-commits or --reachable.)
With the --stdin-commits option, generate the new commit graph by walking commits starting at the commits specified in stdin as a list of OIDs in hex, one OID per line. OIDs that resolve to non-commits (either directly, or by peeling tags) are silently ignored. OIDs that are malformed, or do not exist generate an error. (Cannot be combined with --stdin-packs or --reachable.)
With the --reachable option, generate the new commit graph by walking commits starting at all refs. (Cannot be combined with --stdin-commits or --stdin-packs.)
With the --append option, include all commits that are present in the existing commit-graph file.
With the --changed-paths option, compute and write information about the paths changed between a commit and its first parent. This operation can take a while on large repositories. It provides significant performance gains for getting history of a directory or a file with git log -- <path>. If this option is given, future commit-graph writes will automatically assume that this option was intended. Use --no-changed-paths to stop storing this data.
With the --max-new-filters=<n> option, generate at most n new Bloom filters (if --changed-paths is specified). If n is -1, no limit is enforced. Only commits present in the new layer count against this limit. To retroactively compute Bloom filters over earlier layers, it is advised to use --split=replace. Overrides the commitGraph.maxNewFilters configuration.
With the --split[=<strategy>] option, write the commit-graph as a chain of multiple commit-graph files stored in <dir>/info/commit-graphs. Commit-graph layers are merged based on the strategy and other splitting options. The new commits not already in the commit-graph are added in a new "tip" file. This file is merged with the existing file if the following merge conditions are met:
If --max-commits=<M> is specified with M a positive integer, and the new tip file would have more than M commits, then instead merge the new tip with the previous tip.
Finally, if --expire-time=<datetime> is not specified, let datetime be the current time. After writing the split commit-graph, delete all unused commit-graph whose modified times are older than datetime.
Read the commit-graph file and verify its contents against the object database. Used to check for corrupted data.
With the --shallow option, only check the tip commit-graph file in a chain of split commit-graphs.
Write a commit-graph file for the packed commits in your local .git directory.
$ git commit-graph write
Write a commit-graph file, extending the current commit-graph file using commits in <pack-index>.
$ echo <pack-index> | git commit-graph write --stdin-packs
Write a commit-graph file containing all reachable commits.
$ git show-ref -s | git commit-graph write --stdin-commits
Write a commit-graph file containing all commits in the current commit-graph file along with those reachable from HEAD.
$ git rev-parse HEAD | git commit-graph write --stdin-commits --append
Everything below this line in this section is selectively included from the the section called “git-config(1)” documentation. The content is the same as what's found there:
Specifies the version of the changed-path Bloom filters that Git will read and write. May be -1, 0, 1, or 2. Note that values greater than 1 may be incompatible with older versions of Git which do not yet understand those versions. Use caution when operating in a mixed-version environment.
Defaults to -1.
If -1, Git will use the version of the changed-path Bloom filters in the repository, defaulting to 1 if there are none.
If 0, Git will not read any Bloom filters, and will write version 1 Bloom filters when instructed to write.
If 1, Git will only read version 1 Bloom filters, and will write version 1 Bloom filters.
If 2, Git will only read version 2 Bloom filters, and will write version 2 Bloom filters.
See the section called “git-commit-graph(1)” for more information.
Part of the the section called “git(1)” suite
git commit-tree <tree> [(-p <parent>)…]
git commit-tree [(-p <parent>)…] [-S[<keyid>]] [(-m <message>)…]
[(-F <file>)…] <tree>
This is usually not what an end user wants to run directly. See the section called “git-commit(1)” instead.
Creates a new commit object based on the provided tree object and emits the new commit object id on stdout. The log message is read from the standard input, unless -m or -F options are given.
The -m and -F options can be given any number of times, in any order. The commit log message will be composed in the order in which the options are given.
A commit object may have any number of parents. With exactly one parent, it is an ordinary commit. Having more than one parent makes the commit a merge between several lines of history. Initial (root) commits have no parents.
While a tree represents a particular directory state of a working directory, a commit represents that state in "time", and explains how to get there.
Normally a commit would identify a new "HEAD" state, and while Git doesn't care where you save the note about that state, in practice we tend to just write the result to the file that is pointed at by .git/HEAD, so that we can always see what the last committed state was.
A commit encapsulates:
A commit comment is read from stdin. If a changelog entry is not provided via "<" redirection, git commit-tree will just wait for one to be entered and terminated with ^D.
The GIT_AUTHOR_DATE and GIT_COMMITTER_DATE environment variables support the following date formats:
Time and date specified by the ISO 8601 standard, for example 2005-04-07T22:13:13. The parser accepts a space instead of the T character as well. Fractional parts of a second will be ignored, for example 2005-04-07T22:13:13.019 will be treated as 2005-04-07T22:13:13.
In addition, the date part is accepted in the following formats: YYYY.MM.DD, MM/DD/YYYY and DD.MM.YYYY.
Git is to some extent character encoding agnostic.
Path names are encoded in UTF-8 normalization form C. This applies to tree objects, the index file, ref names, as well as path names in command line arguments, environment variables and config files (.git/config (see the section called “git-config(1)”), the section called “gitignore(5)”, the section called “gitattributes(5)” and the section called “gitmodules(5)”).
Note that Git at the core level treats path names simply as sequences of non-NUL bytes, there are no path name encoding conversions (except on Mac and Windows). Therefore, using non-ASCII path names will mostly work even on platforms and file systems that use legacy extended ASCII encodings. However, repositories created on such systems will not work properly on UTF-8-based systems (e.g. Linux, Mac, Windows) and vice versa. Additionally, many Git-based tools simply assume path names to be UTF-8 and will fail to display other encodings correctly.
Although we encourage that the commit log messages are encoded in UTF-8, both the core and Git Porcelain are designed not to force UTF-8 on projects. If all participants of a particular project find it more convenient to use legacy encodings, Git does not forbid it. However, there are a few things to keep in mind.
git commit and git commit-tree issue a warning if the commit log message given to it does not look like a valid UTF-8 string, unless you explicitly say your project uses a legacy encoding. The way to say this is to have i18n.commitEncoding in .git/config file, like this:
[i18n]
commitEncoding = ISO-8859-1Commit objects created with the above setting record the value of i18n.commitEncoding in their encoding header. This is to help other people who look at them later. Lack of this header implies that the commit log message is encoded in UTF-8.
git log, git show, git blame and friends look at the encoding header of a commit object, and try to re-code the log message into UTF-8 unless otherwise specified. You can specify the desired output encoding with i18n.logOutputEncoding in .git/config file, like this:
[i18n]
logOutputEncoding = ISO-8859-1If you do not have this configuration variable, the value of i18n.commitEncoding is used instead.
Note that we deliberately chose not to re-code the commit log message when a commit is made to force UTF-8 at the commit object level, because re-coding to UTF-8 is not necessarily a reversible operation.
Part of the the section called “git(1)” suite
gitcommit[-a|--interactive|--patch] [-s] [-v] [-u[<mode>]] [--amend]
[--dry-run] [(-c|-C|--squash) <commit> |--fixup[(amend|reword):]<commit>]
[-F<file> |-m<msg>] [--reset-author] [--allow-empty]
[--allow-empty-message] [--no-verify] [-e] [--author=<author>]
[--date=<date>] [--cleanup=<mode>] [--[no-]status]
[-i|-o] [--pathspec-from-file=<file> [--pathspec-file-nul]]
[(--trailer<token>[(=|:)<value>])…] [-S[<keyid>]]
[--] [<pathspec>…]
Create a new commit containing the current contents of the index and the given log message describing the changes. The new commit is a direct child of HEAD, usually the tip of the current branch, and the branch is updated to point to it (unless no branch is associated with the working tree, in which case HEAD is "detached" as described in the section called “git-checkout(1)”).
The content to be committed can be specified in several ways:
The --dry-run option can be used to obtain a summary of what is included by any of the above for the next commit by giving the same set of parameters (options and paths).
If you make a commit and then find a mistake immediately after that, you can recover from it with git reset.
Create a new commit which "fixes up" <commit> when applied with git rebase --autosquash. Plain --fixup=<commit> creates a "fixup!" commit which changes the content of <commit> but leaves its log message untouched. --fixup=amend:<commit> is similar but creates an "amend!" commit which also replaces the log message of <commit> with the log message of the "amend!" commit. --fixup=reword:<commit> creates an "amend!" commit which replaces the log message of <commit> with its own log message but makes no changes to the content of <commit>.
The commit created by plain --fixup=<commit> has a title composed of "fixup!" followed by the title of <commit>, and is recognized specially by git rebase --autosquash. The -m option may be used to supplement the log message of the created commit, but the additional commentary will be thrown away once the "fixup!" commit is squashed into <commit> by git rebase --autosquash.
The commit created by --fixup=amend:<commit> is similar but its title is instead prefixed with "amend!". The log message of <commit> is copied into the log message of the "amend!" commit and opened in an editor so it can be refined. When git rebase --autosquash squashes the "amend!" commit into <commit>, the log message of <commit> is replaced by the refined log message from the "amend!" commit. It is an error for the "amend!" commit's log message to be empty unless --allow-empty-message is specified.
--fixup=reword:<commit> is shorthand for --fixup=amend:<commit> --only. It creates an "amend!" commit with only a log message (ignoring any changes staged in the index). When squashed by git rebase --autosquash, it replaces the log message of <commit> without making any other changes.
Neither "fixup!" nor "amend!" commits change authorship of <commit> when applied by git rebase --autosquash. See the section called “git-rebase(1)” for details.
Use <msg> as the commit message. If multiple -m options are given, their values are concatenated as separate paragraphs.
The -m option is mutually exclusive with -c, -C, and -F.
Add a Signed-off-by trailer by the committer at the end of the commit log message. The meaning of a signoff depends on the project to which you're committing. For example, it may certify that the committer has the rights to submit the work under the project's license or agrees to some contributor representation, such as a Developer Certificate of Origin. (See https://developercertificate.org for the one used by the Linux kernel and Git projects.) Consult the documentation or leadership of the project to which you're contributing to understand how the signoffs are used in that project.
The --no-signoff option can be used to countermand an earlier --signoff option on the command line.
Determine how the supplied commit message should be cleaned up before committing. The <mode> can be strip, whitespace, verbatim, scissors or default.
Same as whitespace except that everything from (and including) the line found below is truncated, if the message is to be edited. "#" can be customized with core.commentChar.
# ------------------------ >8 ------------------------
The default can be changed by the commit.cleanup configuration variable (see the section called “git-config(1)”).
Replace the tip of the current branch by creating a new commit. The recorded tree is prepared as usual (including the effect of the -i and -o options and explicit pathspec), and the message from the original commit is used as the starting point, instead of an empty message, when no other message is specified from the command line via options such as -m, -F, -c, etc. The new commit has the same parents and author as the current one (the --reset-author option can countermand this).
It is a rough equivalent for:
$ git reset --soft HEAD^
$ ... do something else to come up with the right tree ...
$ git commit -c ORIG_HEADbut can be used to amend a merge commit.
You should understand the implications of rewriting history if you amend a commit that has already been published. (See the "RECOVERING FROM UPSTREAM REBASE" section in the section called “git-rebase(1)”.)
Show untracked files.
The <mode> parameter is optional (defaults to all), and is used to specify the handling of untracked files; when -u is not used, the default is normal, i.e. show untracked files and directories.
The possible options are:
All usual spellings for Boolean value true are taken as normal and false as no. The default can be changed using the status.showUntrackedFiles configuration variable documented in the section called “git-config(1)”.
Show unified diff between the HEAD commit and what would be committed at the bottom of the commit message template to help the user describe the commit by reminding what changes the commit has. Note that this diff output doesn't have its lines prefixed with #. This diff will not be a part of the commit message. See the commit.verbose configuration variable in the section called “git-config(1)”.
If specified twice, show in addition the unified diff between what would be committed and the worktree files, i.e. the unstaged changes to tracked files.
When <pathspec> is given on the command line, commit the contents of the files that match the pathspec without recording the changes already added to the index. The contents of these files are also staged for the next commit on top of what have been staged before.
For more details, see the pathspec entry in the section called “gitglossary(7)”.
When recording your own work, the contents of modified files in your working tree are temporarily stored to a staging area called the "index" with git add. A file can be reverted back, only in the index but not in the working tree, to that of the last commit with git restore --staged <file>, which effectively reverts git add and prevents the changes to this file from participating in the next commit. After building the state to be committed incrementally with these commands, git commit (without any pathname parameter) is used to record what has been staged so far. This is the most basic form of the command. An example:
$ edit hello.c $ git rm goodbye.c $ git add hello.c $ git commit
Instead of staging files after each individual change, you can tell git commit to notice the changes to the files whose contents are tracked in your working tree and do corresponding git add and git rm for you. That is, this example does the same as the earlier example if there is no other change in your working tree:
$ edit hello.c $ rm goodbye.c $ git commit -a
The command git commit -a first looks at your working tree, notices that you have modified hello.c and removed goodbye.c, and performs necessary git add and git rm for you.
After staging changes to many files, you can alter the order the changes are recorded in, by giving pathnames to git commit. When pathnames are given, the command makes a commit that only records the changes made to the named paths:
$ edit hello.c hello.h $ git add hello.c hello.h $ edit Makefile $ git commit Makefile
This makes a commit that records the modification to Makefile. The changes staged for hello.c and hello.h are not included in the resulting commit. However, their changes are not lost -- they are still staged and merely held back. After the above sequence, if you do:
$ git commit
this second commit would record the changes to hello.c and hello.h as expected.
After a merge (initiated by git merge or git pull) stops because of conflicts, cleanly merged paths are already staged to be committed for you, and paths that conflicted are left in unmerged state. You would have to first check which paths are conflicting with git status and after fixing them manually in your working tree, you would stage the result as usual with git add:
$ git status | grep unmerged unmerged: hello.c $ edit hello.c $ git add hello.c
After resolving conflicts and staging the result, git ls-files -u would stop mentioning the conflicted path. When you are done, run git commit to finally record the merge:
$ git commit
As with the case to record your own changes, you can use -a option to save typing. One difference is that during a merge resolution, you cannot use git commit with pathnames to alter the order the changes are committed, because the merge should be recorded as a single commit. In fact, the command refuses to run when given pathnames (but see -i option).
Author and committer information is taken from the following environment variables, if set:
(nb "<", ">" and "\n"s are stripped)
The author and committer names are by convention some form of a personal name (that is, the name by which other humans refer to you), although Git does not enforce or require any particular form. Arbitrary Unicode may be used, subject to the constraints listed above. This name has no effect on authentication; for that, see the credential.username variable in the section called “git-config(1)”.
In case (some of) these environment variables are not set, the information is taken from the configuration items user.name and user.email, or, if not present, the environment variable EMAIL, or, if that is not set, system user name and the hostname used for outgoing mail (taken from /etc/mailname and falling back to the fully qualified hostname when that file does not exist).
The author.name and committer.name and their corresponding email options override user.name and user.email if set and are overridden themselves by the environment variables.
The typical usage is to set just the user.name and user.email variables; the other options are provided for more complex use cases.
The GIT_AUTHOR_DATE and GIT_COMMITTER_DATE environment variables support the following date formats:
Time and date specified by the ISO 8601 standard, for example 2005-04-07T22:13:13. The parser accepts a space instead of the T character as well. Fractional parts of a second will be ignored, for example 2005-04-07T22:13:13.019 will be treated as 2005-04-07T22:13:13.
In addition, the date part is accepted in the following formats: YYYY.MM.DD, MM/DD/YYYY and DD.MM.YYYY.
In addition to recognizing all date formats above, the --date option will also try to make sense of other, more human-centric date formats, such as relative dates like "yesterday" or "last Friday at noon".
Though not required, it's a good idea to begin the commit message with a single short (no more than 50 characters) line summarizing the change, followed by a blank line and then a more thorough description. The text up to the first blank line in a commit message is treated as the commit title, and that title is used throughout Git. For example, the section called “git-format-patch(1)” turns a commit into email, and it uses the title on the Subject line and the rest of the commit in the body.
Git is to some extent character encoding agnostic.
Path names are encoded in UTF-8 normalization form C. This applies to tree objects, the index file, ref names, as well as path names in command line arguments, environment variables and config files (.git/config (see the section called “git-config(1)”), the section called “gitignore(5)”, the section called “gitattributes(5)” and the section called “gitmodules(5)”).
Note that Git at the core level treats path names simply as sequences of non-NUL bytes, there are no path name encoding conversions (except on Mac and Windows). Therefore, using non-ASCII path names will mostly work even on platforms and file systems that use legacy extended ASCII encodings. However, repositories created on such systems will not work properly on UTF-8-based systems (e.g. Linux, Mac, Windows) and vice versa. Additionally, many Git-based tools simply assume path names to be UTF-8 and will fail to display other encodings correctly.
Although we encourage that the commit log messages are encoded in UTF-8, both the core and Git Porcelain are designed not to force UTF-8 on projects. If all participants of a particular project find it more convenient to use legacy encodings, Git does not forbid it. However, there are a few things to keep in mind.
git commit and git commit-tree issue a warning if the commit log message given to it does not look like a valid UTF-8 string, unless you explicitly say your project uses a legacy encoding. The way to say this is to have i18n.commitEncoding in .git/config file, like this:
[i18n]
commitEncoding = ISO-8859-1Commit objects created with the above setting record the value of i18n.commitEncoding in their encoding header. This is to help other people who look at them later. Lack of this header implies that the commit log message is encoded in UTF-8.
git log, git show, git blame and friends look at the encoding header of a commit object, and try to re-code the log message into UTF-8 unless otherwise specified. You can specify the desired output encoding with i18n.logOutputEncoding in .git/config file, like this:
[i18n]
logOutputEncoding = ISO-8859-1If you do not have this configuration variable, the value of i18n.commitEncoding is used instead.
Note that we deliberately chose not to re-code the commit log message when a commit is made to force UTF-8 at the commit object level, because re-coding to UTF-8 is not necessarily a reversible operation.
The editor used to edit the commit log message will be chosen from the GIT_EDITOR environment variable, the core.editor configuration variable, the VISUAL environment variable, or the EDITOR environment variable (in that order). See the section called “git-var(1)” for details.
Everything above this line in this section isn't included from the the section called “git-config(1)” documentation. The content that follows is the same as what's found there:
This command can run commit-msg, prepare-commit-msg, pre-commit, post-commit and post-rewrite hooks. See the section called “githooks(5)” for more information.
the section called “git-add(1)”, the section called “git-rm(1)”, the section called “git-mv(1)”, the section called “git-merge(1)”, the section called “git-commit-tree(1)”
Part of the the section called “git(1)” suite
git config list [<file-option>] [<display-option>] [--includes]
git config get [<file-option>] [<display-option>] [--includes] [--all] [--regexp] [--value=<value>] [--fixed-value] [--default=<default>] <name>
git config set [<file-option>] [--type=<type>] [--all] [--value=<value>] [--fixed-value] <name> <value>
git config unset [<file-option>] [--all] [--value=<value>] [--fixed-value] <name>
git config rename-section [<file-option>] <old-name> <new-name>
git config remove-section [<file-option>] <name>
git config edit [<file-option>]
git config [<file-option>] --get-colorbool <name> [<stdout-is-tty>]
You can query/set/replace/unset options with this command. The name is actually the section and the key separated by a dot, and the value will be escaped.
Multiple lines can be added to an option by using the --append option. If you want to update or unset an option which can occur on multiple lines, a value-pattern (which is an extended regular expression, unless the --fixed-value option is given) needs to be given. Only the existing values that match the pattern are updated or unset. If you want to handle the lines that do not match the pattern, just prepend a single exclamation mark in front (see also the section called “EXAMPLES”), but note that this only works when the --fixed-value option is not in use.
The --type=<type> option instructs git config to ensure that incoming and outgoing values are canonicalize-able under the given <type>. If no --type=<type> is given, no canonicalization will be performed. Callers may unset an existing --type specifier with --no-type.
When reading, the values are read from the system, global and repository local configuration files by default, and options --system, --global, --local, --worktree and --file <filename> can be used to tell the command to read from only that location (see the section called “FILES”).
When writing, the new value is written to the repository local configuration file by default, and options --system, --global, --worktree, --file <filename> can be used to tell the command to write to that location (you can say --local but that is the default).
This command will fail with non-zero status upon error. Some exit codes are:
On success, the command returns the exit code 0.
A list of all available configuration variables can be obtained using the git help --config command.
Append a comment at the end of new or modified lines.
If _<message>_ begins with one or more whitespaces followed by "#", it is used as-is. If it begins with "#", a space is prepended before it is used. Otherwise, a string " # " (a space followed by a hash followed by a space) is prepended to it. And the resulting string is placed immediately after the value defined for the variable. The _<message>_ must not contain linefeed characters (no multi-line comments are permitted).
For writing options: write to global ~/.gitconfig file rather than the repository .git/config, write to $XDG_CONFIG_HOME/git/config file if this file exists and the ~/.gitconfig file doesn't.
For reading options: read only from global ~/.gitconfig and from $XDG_CONFIG_HOME/git/config rather than from all available files.
See also the section called “FILES”.
For writing options: write to system-wide $(prefix)/etc/gitconfig rather than the repository .git/config.
For reading options: read only from system-wide $(prefix)/etc/gitconfig rather than from all available files.
See also the section called “FILES”.
For writing options: write to the repository .git/config file. This is the default behavior.
For reading options: read only from the repository .git/config rather than from all available files.
See also the section called “FILES”.
For writing options: write to the specified file rather than the repository .git/config.
For reading options: read only from the specified file rather than from all available files.
See also the section called “FILES”.
git config will ensure that any input or output is valid under the given type constraint(s), and will canonicalize outgoing values in <type>'s canonical form.
Valid <type>'s include:
The following modes have been deprecated in favor of subcommands. It is recommended to migrate to the new syntax.
pager.config is only respected when listing configuration, i.e., when using list or get which may return multiple results. The default is to use a pager.
By default, git config will read configuration options from multiple files:
User-specific configuration files. When the XDG_CONFIG_HOME environment variable is not set or empty, $HOME/.config/ is used as $XDG_CONFIG_HOME.
These are also called "global" configuration files. If both files exist, both files are read in the order given above.
You may also provide additional configuration parameters when running any git command by using the -c option. See the section called “git(1)” for details.
Options will be read from all of these files that are available. If the global or the system-wide configuration files are missing or unreadable they will be ignored. If the repository configuration file is missing or unreadable, git config will exit with a non-zero error code. An error message is produced if the file is unreadable, but not if it is missing.
The files are read in the order given above, with last value found taking precedence over values read earlier. When multiple values are taken then all values of a key from all files will be used.
By default, options are only written to the repository specific configuration file. Note that this also affects options like set and unset. git config will only ever change one file at a time.
You can limit which configuration sources are read from or written to by specifying the path of a file with the --file option, or by specifying a configuration scope with --system, --global, --local, or --worktree. For more, see the section called “OPTIONS” above.
Each configuration source falls within a configuration scope. The scopes are:
$XDG_CONFIG_HOME/git/config
~/.gitconfig
GIT_CONFIG_{COUNT,KEY,VALUE} environment variables (see the section called “ENVIRONMENT” below)
the -c option
With the exception of command, each scope corresponds to a command line option: --system, --global, --local, --worktree.
When reading options, specifying a scope will only read options from the files within that scope. When writing options, specifying a scope will write to the files within that scope (instead of the repository specific configuration file). See the section called “OPTIONS” above for a complete description.
Most configuration options are respected regardless of the scope it is defined in, but some options are only respected in certain scopes. See the respective option's documentation for the full details.
Protected configuration refers to the system, global, and command scopes. For security reasons, certain options are only respected when they are specified in protected configuration, and ignored otherwise.
Git treats these scopes as if they are controlled by the user or a trusted administrator. This is because an attacker who controls these scopes can do substantial harm without using Git, so it is assumed that the user's environment protects these scopes against attackers.
See also the section called “FILES”.
If GIT_CONFIG_COUNT is set to a positive number, all environment pairs GIT_CONFIG_KEY_<n> and GIT_CONFIG_VALUE_<n> up to that number will be added to the process's runtime configuration. The config pairs are zero-indexed. Any missing key or value is treated as an error. An empty GIT_CONFIG_COUNT is treated the same as GIT_CONFIG_COUNT=0, namely no pairs are processed. These environment variables will override values in configuration files, but will be overridden by any explicit options passed via git -c.
This is useful for cases where you want to spawn multiple git commands with a common configuration but cannot depend on a configuration file, for example when writing scripts.
Given a .git/config like this:
#
# This is the config file, and
# a '#' or ';' character indicates
# a comment
#
; core variables
[core]
; Don't trust file modes
filemode = false
; Our diff algorithm
[diff]
external = /usr/local/bin/diff-wrapper
renames = true
; Proxy settings
[core]
gitproxy=proxy-command for kernel.org
gitproxy=default-proxy ; for all the rest
; HTTP
[http]
sslVerify
[http "https://weak.example.com"]
sslVerify = false
cookieFile = /tmp/cookie.txtyou can set the filemode to true with
% git config set core.filemode true
The hypothetical proxy command entries actually have a postfix to discern what URL they apply to. Here is how to change the entry for kernel.org to "ssh".
% git config set --value='for kernel.org$' core.gitproxy '"ssh" for kernel.org'
This makes sure that only the key/value pair for kernel.org is replaced.
To delete the entry for renames, do
% git config unset diff.renames
If you want to delete an entry for a multivar (like core.gitproxy above), you have to provide a regex matching the value of exactly one line.
To query the value for a given key, do
% git config get core.filemode
or, to query a multivar:
% git config get --value="for kernel.org$" core.gitproxy
If you want to know all the values for a multivar, do:
% git config get --all --show-names core.gitproxy
If you like to live dangerously, you can replace all core.gitproxy by a new one with
% git config set --all core.gitproxy ssh
However, if you really only want to replace the line for the default proxy, i.e. the one without a "for …" postfix, do something like this:
% git config set --value='! for ' core.gitproxy ssh
To actually match only values with an exclamation mark, you have to
% git config set --value='[!]' section.key value
To add a new proxy, without altering any of the existing ones, use
% git config set --append core.gitproxy '"proxy-command" for example.com'
An example to use customized color from the configuration in your script:
#!/bin/sh
WS=$(git config get --type=color --default="blue reverse" color.diff.whitespace)
RESET=$(git config get --type=color --default="reset" "")
echo "${WS}your whitespace color or blue reverse${RESET}"For URLs in https://weak.example.com, http.sslVerify is set to false, while it is set to true for all others:
% git config get --type=bool --url=https://good.example.com http.sslverify true % git config get --type=bool --url=https://weak.example.com http.sslverify false % git config get --url=https://weak.example.com http http.cookieFile /tmp/cookie.txt http.sslverify false
The Git configuration file contains a number of variables that affect the Git commands' behavior. The files .git/config and optionally config.worktree (see the "CONFIGURATION FILE" section of the section called “git-worktree(1)”) in each repository are used to store the configuration for that repository, and $HOME/.gitconfig is used to store a per-user configuration as fallback values for the .git/config file. The file /etc/gitconfig can be used to store a system-wide default configuration.
The configuration variables are used by both the Git plumbing and the porcelain commands. The variables are divided into sections, wherein the fully qualified variable name of the variable itself is the last dot-separated segment and the section name is everything before the last dot. The variable names are case-insensitive, allow only alphanumeric characters and -, and must start with an alphabetic character. Some variables may appear multiple times; we say then that the variable is multivalued.
The syntax is fairly flexible and permissive. Whitespace characters, which in this context are the space character (SP) and the horizontal tabulation (HT), are mostly ignored. The # and ; characters begin comments to the end of line. Blank lines are ignored.
The file consists of sections and variables. A section begins with the name of the section in square brackets and continues until the next section begins. Section names are case-insensitive. Only alphanumeric characters, - and . are allowed in section names. Each variable must belong to some section, which means that there must be a section header before the first setting of a variable.
Sections can be further divided into subsections. To begin a subsection put its name in double quotes, separated by space from the section name, in the section header, like in the example below:
[section "subsection"]
Subsection names are case sensitive and can contain any characters except newline and the null byte. Doublequote " and backslash can be included by escaping them as \" and \\, respectively. Backslashes preceding other characters are dropped when reading; for example, \t is read as t and \0 is read as 0. Section headers cannot span multiple lines. Variables may belong directly to a section or to a given subsection. You can have [section] if you have [section "subsection"], but you don't need to.
There is also a deprecated [section.subsection] syntax. With this syntax, the subsection name is converted to lower-case and is also compared case sensitively. These subsection names follow the same restrictions as section names.
All the other lines (and the remainder of the line after the section header) are recognized as setting variables, in the form name = value (or just name, which is a short-hand to say that the variable is the boolean "true"). The variable names are case-insensitive, allow only alphanumeric characters and -, and must start with an alphabetic character.
Whitespace characters surrounding name, = and value are discarded. Internal whitespace characters within value are retained verbatim. Comments starting with either # or ; and extending to the end of line are discarded. A line that defines a value can be continued to the next line by ending it with a backslash (\); the backslash and the end-of-line characters are discarded.
If value needs to contain leading or trailing whitespace characters, it must be enclosed in double quotation marks ("). Inside double quotation marks, double quote (") and backslash (\) characters must be escaped: use \" for " and \\ for \.
The following escape sequences (beside \" and \\) are recognized: \n for newline character (NL), \t for horizontal tabulation (HT, TAB) and \b for backspace (BS). Other char escape sequences (including octal escape sequences) are invalid.
The include and includeIf sections allow you to include config directives from another source. These sections behave identically to each other with the exception that includeIf sections may be ignored if their condition does not evaluate to true; see "Conditional includes" below.
You can include a config file from another by setting the special include.path (or includeIf.*.path) variable to the name of the file to be included. The variable takes a pathname as its value, and is subject to tilde expansion. These variables can be given multiple times.
The contents of the included file are inserted immediately, as if they had been found at the location of the include directive. If the value of the variable is a relative path, the path is considered to be relative to the configuration file in which the include directive was found. See below for examples.
You can conditionally include a config file from another by setting an includeIf.<condition>.path variable to the name of the file to be included.
The condition starts with a keyword followed by a colon and some data whose format and meaning depends on the keyword. Supported keywords are:
The data that follows the keyword gitdir: is used as a glob pattern. If the location of the .git directory matches the pattern, the include condition is met.
The .git location may be auto-discovered, or come from $GIT_DIR environment variable. If the repository is auto-discovered via a .git file (e.g. from submodules, or a linked worktree), the .git location would be the final location where the .git directory is, not where the .git file is.
The pattern can contain standard globbing wildcards and two additional ones, **/ and /**, that can match multiple path components. Please refer to the section called “gitignore(5)” for details. For convenience:
The data that follows the keyword onbranch: is taken to be a pattern with standard globbing wildcards and two additional ones, **/ and /**, that can match multiple path components. If we are in a worktree where the name of the branch that is currently checked out matches the pattern, the include condition is met.
If the pattern ends with /, ** will be automatically added. For example, the pattern foo/ becomes foo/**. In other words, it matches all branches that begin with foo/. This is useful if your branches are organized hierarchically and you would like to apply a configuration to all the branches in that hierarchy.
The data that follows this keyword is taken to be a pattern with standard globbing wildcards and two additional ones, **/ and /**, that can match multiple components. The first time this keyword is seen, the rest of the config files will be scanned for remote URLs (without applying any values). If there exists at least one remote URL that matches this pattern, the include condition is met.
Files included by this option (directly or indirectly) are not allowed to contain remote URLs.
Note that unlike other includeIf conditions, resolving this condition relies on information that is not yet known at the point of reading the condition. A typical use case is this option being present as a system-level or global-level config, and the remote URL being in a local-level config; hence the need to scan ahead when resolving this condition. In order to avoid the chicken-and-egg problem in which potentially-included files can affect whether such files are potentially included, Git breaks the cycle by prohibiting these files from affecting the resolution of these conditions (thus, prohibiting them from declaring remote URLs).
As for the naming of this keyword, it is for forwards compatibility with a naming scheme that supports more variable-based include conditions, but currently Git only supports the exact keyword described above.
A few more notes on matching via gitdir and gitdir/i:
Both the symlink & realpath versions of paths will be matched outside of $GIT_DIR. E.g. if ~/git is a symlink to /mnt/storage/git, both gitdir:~/git and gitdir:/mnt/storage/git will match.
This was not the case in the initial release of this feature in v2.13.0, which only matched the realpath version. Configuration that wants to be compatible with the initial release of this feature needs to either specify only the realpath version, or both versions.
# Core variables
[core]
; Don't trust file modes
filemode = false
# Our diff algorithm
[diff]
external = /usr/local/bin/diff-wrapper
renames = true
[branch "devel"]
remote = origin
merge = refs/heads/devel
# Proxy settings
[core]
gitProxy="ssh" for "kernel.org"
gitProxy=default-proxy ; for the rest
[include]
path = /path/to/foo.inc ; include by absolute path
path = foo.inc ; find "foo.inc" relative to the current file
path = ~/foo.inc ; find "foo.inc" in your `$HOME` directory
; include if $GIT_DIR is /path/to/foo/.git
[includeIf "gitdir:/path/to/foo/.git"]
path = /path/to/foo.inc
; include for all repositories inside /path/to/group
[includeIf "gitdir:/path/to/group/"]
path = /path/to/foo.inc
; include for all repositories inside $HOME/to/group
[includeIf "gitdir:~/to/group/"]
path = /path/to/foo.inc
; relative paths are always relative to the including
; file (if the condition is true); their location is not
; affected by the condition
[includeIf "gitdir:/path/to/group/"]
path = foo.inc
; include only if we are in a worktree where foo-branch is
; currently checked out
[includeIf "onbranch:foo-branch"]
path = foo.inc
; include only if a remote with the given URL exists (note
; that such a URL may be provided later in a file or in a
; file read after this file is read, as seen in this example)
[includeIf "hasconfig:remote.*.url:https://example.com/**"]
path = foo.inc
[remote "origin"]
url = https://example.com/gitValues of many variables are treated as a simple string, but there are variables that take values of specific types and there are rules as to how to spell them.
When a variable is said to take a boolean value, many synonyms are accepted for true and false; these are all case-insensitive.
Boolean false literals are no, off, false, 0 and the empty string.
When converting a value to its canonical form using the --type=bool type specifier, git config will ensure that the output is "true" or "false" (spelled in lowercase).
The value for a variable that takes a color is a list of colors (at most two, one for foreground and one for background) and attributes (as many as you want), separated by spaces.
The basic colors accepted are normal, black, red, green, yellow, blue, magenta, cyan, white and default. The first color given is the foreground; the second is the background. All the basic colors except normal and default have a bright variant that can be specified by prefixing the color with bright, like brightred.
The color normal makes no change to the color. It is the same as an empty string, but can be used as the foreground color when specifying a background color alone (for example, "normal red").
The color default explicitly resets the color to the terminal default, for example to specify a cleared background. Although it varies between terminals, this is usually not the same as setting to "white black".
Colors may also be given as numbers between 0 and 255; these use ANSI 256-color mode (but note that not all terminals may support this). If your terminal supports it, you may also specify 24-bit RGB values as hex, like #ff0ab3, or 12-bit RGB values like #f1b, which is equivalent to the 24-bit color #ff11bb.
The accepted attributes are bold, dim, ul, blink, reverse, italic, and strike (for crossed-out or "strikethrough" letters). The position of any attributes with respect to the colors (before, after, or in between), doesn't matter. Specific attributes may be turned off by prefixing them with no or no- (e.g., noreverse, no-ul, etc).
The pseudo-attribute reset resets all colors and attributes before applying the specified coloring. For example, reset green will result in a green foreground and default background without any active attributes.
An empty color string produces no color effect at all. This can be used to avoid coloring specific elements without disabling color entirely.
For git's pre-defined color slots, the attributes are meant to be reset at the beginning of each item in the colored output. So setting color.decorate.branch to black will paint that branch name in a plain black, even if the previous thing on the same output line (e.g. opening parenthesis before the list of branch names in log --decorate output) is set to be painted with bold or some other attribute. However, custom log formats may do more complicated and layered coloring, and the negated forms may be useful there.
A variable that takes a pathname value can be given a string that begins with "~/" or "~user/", and the usual tilde expansion happens to such a string: ~/ is expanded to the value of $HOME, and ~user/ to the specified user's home directory.
If a path starts with %(prefix)/, the remainder is interpreted as a path relative to Git's "runtime prefix", i.e. relative to the location where Git itself was installed. For example, %(prefix)/bin/ refers to the directory in which the Git executable itself lives. If Git was compiled without runtime prefix support, the compiled-in prefix will be substituted instead. In the unlikely event that a literal path needs to be specified that should not be expanded, it needs to be prefixed by ./, like so: ./%(prefix)/bin.
Note that this list is non-comprehensive and not necessarily complete. For command-specific variables, you will find a more detailed description in the appropriate manual page.
Other git-related tools may and do use their own variables. When inventing new variables for use in your own tool, make sure their names do not conflict with those that are used by Git itself and other popular tools, and describe them in your documentation.
These variables control various optional help messages designed to aid new users. When left unconfigured, Git will give the message alongside instructions on how to squelch it. You can tell Git that you have understood the issue and no longer need a specific help message by setting the corresponding variable to false.
As they are intended to help human users, these messages are output to the standard error. When tools that run Git as a subprocess find them disruptive, they can set GIT_ADVICE=0 in the environment to squelch all advice messages.
Command aliases for the the section called “git(1)” command wrapper - e.g. after defining alias.last = cat-file commit HEAD, the invocation git last is equivalent to git cat-file commit HEAD. To avoid confusion and troubles with script usage, aliases that hide existing Git commands are ignored. Arguments are split by spaces, the usual shell quoting and escaping are supported. A quote pair or a backslash can be used to quote them.
Note that the first word of an alias does not necessarily have to be a command. It can be a command-line option that will be passed into the invocation of git. In particular, this is useful when used with -c to pass in one-time configurations or -p to force pagination. For example, loud-rebase = -c commit.verbose=true rebase can be defined such that running git loud-rebase would be equivalent to git -c commit.verbose=true rebase. Also, ps = -p status would be a helpful alias since git ps would paginate the output of git status where the original command does not.
If the alias expansion is prefixed with an exclamation point, it will be treated as a shell command. For example, defining alias.new = !gitk --all --not ORIG_HEAD, the invocation git new is equivalent to running the shell command gitk --all --not ORIG_HEAD. Note:
Shell command aliases always receive any extra arguments provided to the Git command-line as positional arguments.
The configuration options in bitmapPseudoMerge.* are considered EXPERIMENTAL and may be subject to change or be removed entirely in the future. For more information about the pseudo-merge bitmap feature, see the "Pseudo-merge bitmaps" section of the section called “gitpacking(7)”.
Regular expression used to match reference names. Commits pointed to by references matching this pattern (and meeting the below criteria, like bitmapPseudoMerge.<name>.sampleRate and bitmapPseudoMerge.<name>.threshold) will be considered for inclusion in a pseudo-merge bitmap.
Commits are grouped into pseudo-merge groups based on whether or not any reference(s) that point at a given commit match the pattern, which is an extended regular expression.
Within a pseudo-merge group, commits may be further grouped into sub-groups based on the capture groups in the pattern. These sub-groupings are formed from the regular expressions by concatenating any capture groups from the regular expression, with a - dash in between.
For example, if the pattern is refs/tags/, then all tags (provided they meet the below criteria) will be considered candidates for the same pseudo-merge group. However, if the pattern is instead refs/remotes/([0-9])+/tags/, then tags from different remotes will be grouped into separate pseudo-merge groups, based on the remote number.
Determines the rate at which consecutive pseudo-merge bitmap groups decrease in size. Must be non-negative. This parameter can be thought of as k in the function f(n) = C * n^-k, where f(n) is the size of the `n`th group.
Setting the decay rate equal to 0 will cause all groups to be the same size. Setting the decay rate equal to 1 will cause the n`th group to be `1/n the size of the initial group. Higher values of the decay rate cause consecutive groups to shrink at an increasing rate. The default is 1.
If all groups are the same size, it is possible that groups containing newer commits will be able to be used less often than earlier groups, since it is more likely that the references pointing at newer commits will be updated more often than a reference pointing at an old commit.
Determines the maximum number of pseudo-merge commits among which commits may be distributed.
For pseudo-merge groups whose pattern does not contain any capture groups, this setting is applied for all commits matching the regular expression. For patterns that have one or more capture groups, this setting is applied for each distinct capture group.
For example, if your capture group is refs/tags/, then this setting will distribute all tags into a maximum of maxMerges pseudo-merge commits. However, if your capture group is, say, refs/remotes/([0-9]+)/tags/, then this setting will be applied to each remote's set of tags individually.
Must be non-negative. The default value is 64.
Determines the minimum age of commits (among reference tips, as above, however stable commits are still considered candidates even when they have been covered by a bitmap) which are candidates for a stable a pseudo-merge bitmap. The default is 1.month.ago.
Setting this threshold to a smaller value (e.g., 1.week.ago) will cause more stable groups to be generated (which impose a one-time generation cost) but those groups will likely become stale over time. Using a larger value incurs the opposite penalty (fewer stable groups which are more useful).
Tells git branch, git switch and git checkout to set up new branches so that the section called “git-pull(1)” will appropriately merge from the starting point branch. Note that even if this option is not set, this behavior can be chosen per-branch using the --track and --no-track options. This option defaults to true. The valid settings are:
When a new branch is created with git branch, git switch or git checkout that tracks another branch, this variable tells Git to set up pull to rebase instead of merge (see branch.<name>.rebase). The valid settings are:
See branch.autoSetupMerge for details on how to set up a branch to track another branch. This option defaults to never.
When true, rebase the branch <name> on top of the fetched branch, instead of merging the default branch from the default remote when git pull is run. See pull.rebase for doing this in a non branch-specific manner.
When merges (or just m), pass the --rebase-merges option to git rebase so that the local merge commits are included in the rebase (see the section called “git-rebase(1)” for details).
When the value is interactive (or just i), the rebase is run in interactive mode.
NOTE: this is a possibly dangerous operation; do not use it unless you understand the implications (see the section called “git-rebase(1)” for details).
When you run git checkout <something> or git switch <something> and only have one remote, it may implicitly fall back on checking out and tracking e.g. origin/<something>. This stops working as soon as you have more than one remote with a <something> reference. This setting allows for setting the name of a preferred remote that should always win when it comes to disambiguation. The typical use-case is to set this to origin.
Currently this is used by the section called “git-switch(1)” and the section called “git-checkout(1)” when git checkout <something> or git switch <something> will checkout the <something> branch on another remote, and by the section called “git-worktree(1)” when git worktree add refers to a remote branch. This setting might be used for other checkout-like commands or functionality in the future.
The number of parallel workers to use when updating the working tree. The default is one, i.e. sequential execution. If set to a value less than one, Git will use as many workers as the number of logical cores available. This setting and checkout.thresholdForParallelism affect all commands that perform checkout. E.g. checkout, clone, reset, sparse-checkout, etc.
Parallel checkout usually delivers better performance for repositories located on SSDs or over NFS. For repositories on spinning disks and/or machines with a small number of cores, the default sequential checkout often performs better. The size and compression level of a repository might also influence how well the parallel version performs.
Specify the line annotation color for git blame --color-by-age depending upon the age of the line.
This setting should be set to a comma-separated list of color and date settings, starting and ending with a color, the dates should be set from oldest to newest. The metadata will be colored with the specified colors if the line was introduced before the given timestamp, overwriting older timestamped colors.
Instead of an absolute timestamp relative timestamps work as well, e.g. 2.weeks.ago is valid to address anything older than 2 weeks.
It defaults to blue,12 month ago,white,1 month ago,red, which colors everything older than one year blue, recent changes between one month and one year old are kept white, and lines introduced within the last month are colored red.
Whether to use ANSI escape sequences to add color to patches. If this is set to always, the section called “git-diff(1)”, the section called “git-log(1)”, and the section called “git-show(1)” will use color for all patches. If it is set to true or auto, those commands will only use color when output is to the terminal. If unset, then the value of color.ui is used (auto by default).
This does not affect the section called “git-format-patch(1)” or the git-diff-* plumbing commands. Can be overridden on the command line with the --color[=<when>] option.
Use customized color for grep colorization. <slot> specifies which part of the line to use the specified color, and is one of
Specify whether supported commands should output in columns. This variable consists of a list of tokens separated by spaces or commas:
These options control when the feature should be enabled (defaults to never):
These options control layout (defaults to column). Setting any of these implies always if none of always, never, or auto are specified.
Finally, these options can be combined with a layout option (defaults to nodense):
Specifies the version of the changed-path Bloom filters that Git will read and write. May be -1, 0, 1, or 2. Note that values greater than 1 may be incompatible with older versions of Git which do not yet understand those versions. Use caution when operating in a mixed-version environment.
Defaults to -1.
If -1, Git will use the version of the changed-path Bloom filters in the repository, defaulting to 1 if there are none.
If 0, Git will not read any Bloom filters, and will write version 1 Bloom filters when instructed to write.
If 1, Git will only read version 1 Bloom filters, and will write version 1 Bloom filters.
If 2, Git will only read version 2 Bloom filters, and will write version 2 Bloom filters.
See the section called “git-commit-graph(1)” for more information.
Tells Git if the executable bit of files in the working tree is to be honored.
Some filesystems lose the executable bit when a file that is marked as executable is checked out, or checks out a non-executable file with executable bit on. the section called “git-clone(1)” or the section called “git-init(1)” probe the filesystem to see if it handles the executable bit correctly and this variable is automatically set as necessary.
A repository, however, may be on a filesystem that handles the filemode correctly, and this variable is set to true when created, but later may be made accessible from another environment that loses the filemode (e.g. exporting ext4 via CIFS mount, visiting a Cygwin created repository with Git for Windows or Eclipse). In such a case it may be necessary to set this variable to false. See the section called “git-update-index(1)”.
The default is true (when core.filemode is not specified in the config file).
Internal variable which enables various workarounds to enable Git to work better on filesystems that are not case sensitive, like APFS, HFS+, FAT, NTFS, etc. For example, if a directory listing finds "makefile" when Git expects "Makefile", Git will assume it is really the same file, and continue to remember it as "Makefile".
The default is false, except the section called “git-clone(1)” or the section called “git-init(1)” will probe and set core.ignoreCase true if appropriate when the repository is created.
Git relies on the proper configuration of this variable for your operating and file system. Modifying this value may result in unexpected behavior.
If set to true, enable the built-in file system monitor daemon for this working directory (the section called “git-fsmonitor--daemon(1)”).
Like hook-based file system monitors, the built-in file system monitor can speed up Git commands that need to refresh the Git index (e.g. git status) in a working directory with many files. The built-in monitor eliminates the need to install and maintain an external third-party tool.
The built-in file system monitor is currently available only on a limited set of supported platforms. Currently, this includes Windows and MacOS.
Otherwise, this variable contains the pathname of the "fsmonitor" hook command.
This hook command is used to identify all files that may have changed since the requested date/time. This information is used to speed up git by avoiding unnecessary scanning of files that have not changed.
See the "fsmonitor-watchman" section of the section called “githooks(5)”.
Note that if you concurrently use multiple versions of Git, such as one version on the command line and another version in an IDE tool, that the definition of core.fsmonitor was extended to allow boolean values in addition to hook pathnames. Git versions 2.35.1 and prior will not understand the boolean values and will consider the "true" or "false" values as hook pathnames to be invoked. Git versions 2.26 thru 2.35.1 default to hook protocol V2 and will fall back to no fsmonitor (full scan). Git versions prior to 2.26 default to hook protocol V1 and will silently assume there were no changes to report (no scan), so status commands may report incomplete results. For this reason, it is best to upgrade all of your Git versions before using the built-in file system monitor.
Sets the protocol version to be used when invoking the "fsmonitor" hook.
There are currently versions 1 and 2. When this is not set, version 2 will be tried first and if it fails then version 1 will be tried. Version 1 uses a timestamp as input to determine which files have changes since that time but some monitors like Watchman have race conditions when used with a timestamp. Version 2 uses an opaque string so that the monitor can return something that can be used to determine what files have changed without race conditions.
When missing or is set to default, many fields in the stat structure are checked to detect if a file has been modified since Git looked at it. When this configuration variable is set to minimal, sub-second part of mtime and ctime, the uid and gid of the owner of the file, the inode number (and the device number, if Git was compiled to use it), are excluded from the check among these fields, leaving only the whole-second part of mtime (and ctime, if core.trustCtime is set) and the filesize to be checked.
There are implementations of Git that do not leave usable values in some fields (e.g. JGit); by excluding these fields from the comparison, the minimal mode may help interoperability when the same repository is used by these other systems at the same time.
If true, makes Git check if converting CRLF is reversible when end-of-line conversion is active. Git will verify if a command modifies a file in the work tree either directly or indirectly. For example, committing a file followed by checking out the same file should yield the original file in the work tree. If this is not the case for the current setting of core.autocrlf, Git will reject the file. The variable can be set to "warn", in which case Git will only warn about an irreversible conversion but continue the operation.
CRLF conversion bears a slight chance of corrupting data. When it is enabled, Git will convert CRLF to LF during commit and LF to CRLF during checkout. A file that contains a mixture of LF and CRLF before the commit cannot be recreated by Git. For text files this is the right thing to do: it corrects line endings such that we have only LF line endings in the repository. But for binary files that are accidentally classified as text the conversion can corrupt data.
If you recognize such corruption early you can easily fix it by setting the conversion type explicitly in .gitattributes. Right after committing you still have the original file in your work tree and this file is not yet corrupted. You can explicitly tell Git that this file is binary and Git will handle the file appropriately.
Unfortunately, the desired effect of cleaning up text files with mixed line endings and the undesired effect of corrupting binary files cannot be distinguished. In both cases CRLFs are removed in an irreversible way. For text files this is the right thing to do because CRLFs are line endings, while for binary files converting CRLFs corrupts data.
Note, this safety check does not mean that a checkout will generate a file identical to the original file for a different setting of core.eol and core.autocrlf, but only for the current one. For example, a text file with LF would be accepted with core.eol=lf and could later be checked out with core.eol=crlf, in which case the resulting file would contain CRLF, although the original file contained LF. However, in both work trees the line endings would be consistent, that is either all LF or all CRLF, but never mixed. A file with mixed line endings would be reported by the core.safecrlf mechanism.
If false, symbolic links are checked out as small plain files that contain the link text. the section called “git-update-index(1)” and the section called “git-add(1)” will not change the recorded type to regular file. Useful on filesystems like FAT that do not support symbolic links.
The default is true, except the section called “git-clone(1)” or the section called “git-init(1)” will probe and set core.symlinks false if appropriate when the repository is created.
A "proxy command" to execute (as command host port) instead of establishing direct connection to the remote server when using the Git protocol for fetching. If the variable value is in the "COMMAND for DOMAIN" format, the command is applied only on hostnames ending with the specified domain string. This variable may be set multiple times and is matched in the given order; the first match wins.
Can be overridden by the GIT_PROXY_COMMAND environment variable (which always applies universally, without the special "for" handling).
The special string none can be used as the proxy command to specify that no proxy be used for a given domain pattern. This is useful for excluding servers inside a firewall from proxy use, while defaulting to a common proxy for external domains.
If true, Git will avoid using lstat() calls to detect if files have changed by setting the "assume-unchanged" bit for those tracked files which it has updated identically in both the index and working tree.
When files are modified outside of Git, the user will need to stage the modified files explicitly (e.g. see Examples section in the section called “git-update-index(1)”). Git will not normally detect changes to those files.
This is useful on systems where lstat() calls are very slow, such as CIFS/Microsoft Windows.
False by default.
When advertising tips of available history from an alternate, use the shell to execute the specified command instead of the section called “git-for-each-ref(1)”. The first argument is the absolute path of the alternate. Output must contain one hex object id per line (i.e., the same as produced by git for-each-ref --format='%(objectname)').
Note that you cannot generally put git for-each-ref directly into the config value, as it does not take a repository path as an argument (but you can wrap the command above in a shell script).
If true this repository is assumed to be bare and has no working directory associated with it. If this is the case a number of commands that require a working directory will be disabled, such as the section called “git-add(1)” or the section called “git-merge(1)”.
This setting is automatically guessed by the section called “git-clone(1)” or the section called “git-init(1)” when the repository was created. By default a repository that ends in "/.git" is assumed to be not bare (bare = false), while all other repositories are assumed to be bare (bare = true).
Set the path to the root of the working tree. If GIT_COMMON_DIR environment variable is set, core.worktree is ignored and not used for determining the root of working tree. This can be overridden by the GIT_WORK_TREE environment variable and the --work-tree command-line option. The value can be an absolute path or relative to the path to the .git directory, which is either specified by --git-dir or GIT_DIR, or automatically discovered. If --git-dir or GIT_DIR is specified but none of --work-tree, GIT_WORK_TREE and core.worktree is specified, the current working directory is regarded as the top level of your working tree.
Note that this variable is honored even when set in a configuration file in a ".git" subdirectory of a directory and its value differs from the latter directory (e.g. "/path/to/.git/config" has core.worktree set to "/different/path"), which is most likely a misconfiguration. Running Git commands in the "/path/to" directory will still use "/different/path" as the root of the work tree and can cause confusion unless you know what you are doing (e.g. you are creating a read-only snapshot of the same index to a location different from the repository's usual working tree).
Enable the reflog. Updates to a ref <ref> is logged to the file "$GIT_DIR/logs/<ref>", by appending the new and old SHA-1, the date/time and the reason of the update, but only when the file exists. If this configuration variable is set to true, missing "$GIT_DIR/logs/<ref>" file is automatically created for branch heads (i.e. under refs/heads/), remote refs (i.e. under refs/remotes/), note refs (i.e. under refs/notes/), and the symbolic ref HEAD. If it is set to always, then a missing reflog is automatically created for any ref under refs/.
This information can be used to determine what commit was the tip of a branch "2 days ago".
This value is true by default in a repository that has a working directory associated with it, and false by default in a bare repository.
Number of bytes of a pack file to map into memory in a single mapping operation. Larger window sizes may allow your system to process a smaller number of large pack files more quickly. Smaller window sizes will negatively affect performance due to increased calls to the operating system's memory manager, but may improve performance when accessing a large number of large pack files.
Default is 1 MiB if NO_MMAP was set at compile time, otherwise 32 MiB on 32 bit platforms and 1 GiB on 64 bit platforms. This should be reasonable for all users/operating systems. You probably do not need to adjust this value.
Common unit suffixes of k, m, or g are supported.
Maximum number of bytes to map simultaneously into memory from pack files. If Git needs to access more than this many bytes at once to complete an operation it will unmap existing regions to reclaim virtual address space within the process.
Default is 256 MiB on 32 bit platforms and 32 TiB (effectively unlimited) on 64 bit platforms. This should be reasonable for all users/operating systems, except on the largest projects. You probably do not need to adjust this value.
Common unit suffixes of k, m, or g are supported.
Maximum number of bytes per thread to reserve for caching base objects that may be referenced by multiple deltified objects. By storing the entire decompressed base objects in a cache Git is able to avoid unpacking and decompressing frequently used base objects multiple times.
Default is 96 MiB on all platforms. This should be reasonable for all users/operating systems, except on the largest projects. You probably do not need to adjust this value.
Common unit suffixes of k, m, or g are supported.
The size of files considered "big", which as discussed below changes the behavior of numerous git commands, as well as how such files are stored within the repository. The default is 512 MiB. Common unit suffixes of k, m, or g are supported.
Files above the configured limit will be:
Stored deflated in packfiles, without attempting delta compression.
The default limit is primarily set with this use-case in mind. With it, most projects will have their source code and other text files delta compressed, but not larger binary media files.
Storing large files without delta compression avoids excessive memory usage, at the slight expense of increased disk usage.
By default Git will look for your hooks in the $GIT_DIR/hooks directory. Set this to different path, e.g. /etc/git/hooks, and Git will try to find your hooks in that directory, e.g. /etc/git/hooks/pre-receive instead of in $GIT_DIR/hooks/pre-receive.
The path can be either absolute or relative. A relative path is taken as relative to the directory where the hooks are run (see the "DESCRIPTION" section of the section called “githooks(5)”).
This configuration variable is useful in cases where you'd like to centrally configure your Git hooks instead of configuring them on a per-repository basis, or as a more flexible and centralized alternative to having an init.templateDir where you've changed default hooks.
You can also disable all hooks entirely by setting core.hooksPath to /dev/null. This is usually only advisable for expert users and on a per-command basis using configuration parameters of the form git -c core.hooksPath=/dev/null ....
Commands such as commit and tag that let you edit messages consider a line that begins with this character commented, and removes them after the editor returns (default #).
If set to "auto", git-commit would select a character that is not the beginning character of any line in existing commit messages.
Note that these two variables are aliases of each other, and in modern versions of Git you are free to use a string (e.g., // or ⁑⁕⁑) with commentChar. Versions of Git prior to v2.45.0 will ignore commentString but will reject a value of commentChar that consists of more than a single ASCII byte. If you plan to use your config with older and newer versions of Git, you may want to specify both:
[core] # single character for older versions commentChar = "#" # string for newer versions (which will override commentChar # because it comes later in the file) commentString = "//"
Text viewer for use by Git commands (e.g., less). The value is meant to be interpreted by the shell. The order of preference is the $GIT_PAGER environment variable, then core.pager configuration, then $PAGER, and then the default chosen at compile time (usually less).
When the LESS environment variable is unset, Git sets it to FRX (if LESS environment variable is set, Git does not change it at all). If you want to selectively override Git's default setting for LESS, you can set core.pager to e.g. less -S. This will be passed to the shell by Git, which will translate the final command to LESS=FRX less -S. The environment does not set the S option but the command line does, instructing less to truncate long lines. Similarly, setting core.pager to less -+F will deactivate the F option specified by the environment from the command-line, deactivating the "quit if one screen" behavior of less. One can specifically activate some flags for particular commands: for example, setting pager.blame to less -S enables line truncation only for git blame.
Likewise, when the LV environment variable is unset, Git sets it to -c. You can override this setting by exporting LV with another value or setting core.pager to lv +c.
A comma separated list of common whitespace problems to notice. git diff will use color.diff.whitespace to highlight them, and git apply --whitespace=error will consider them as errors. You can prefix - to disable any of them (e.g. -trailing-space):
A comma-separated list of components of the repository that should be hardened via the core.fsyncMethod when created or modified. You can disable hardening of any component by prefixing it with a -. Items that are not hardened may be lost in the event of an unclean system shutdown. Unless you have special requirements, it is recommended that you leave this option empty or pick one of committed, added, or all.
When this configuration is encountered, the set of components starts with the platform default value, disabled components are removed, and additional components are added. none resets the state so that the platform default is ignored.
The empty string resets the fsync configuration to the platform default. The default on most platforms is equivalent to core.fsync=committed,-loose-object, which has good performance, but risks losing recent work in the event of an unclean system shutdown.
A value indicating the strategy Git will use to harden repository data using fsync and related primitives.
batch enables a mode that uses writeout-only flushes to stage multiple updates in the disk writeback cache and then does a single full fsync of a dummy file to trigger the disk cache flush at the end of the operation.
Currently batch mode only applies to loose-object files. Other repository data is made durable as if fsync was specified. This mode is expected to be as safe as fsync on macOS for repos stored on HFS+ or APFS filesystems and on Windows for repos stored on NTFS or ReFS filesystems.
This boolean will enable fsync() when writing object files. This setting is deprecated. Use core.fsync instead.
This setting affects data added to the Git repository in loose-object form. When set to true, Git will issue an fsync or similar system call to flush caches so that loose-objects remain consistent in the face of a unclean system shutdown.
Enable parallel index preload for operations like git diff
This can speed up operations like git diff and git status especially on filesystems like NFS that have weak caching semantics and thus relatively high IO latencies. When enabled, Git will do the index comparison to the filesystem data in parallel, allowing overlapping IO's. Defaults to true.
You can set this to link, in which case a hardlink followed by a delete of the source are used to make sure that object creation will not overwrite existing objects.
On some file system/operating system combinations, this is unreliable. Set this config setting to rename there; however, this will remove the check that makes sure that existing object files will not get overwritten.
When showing commit messages, also show notes which are stored in the given ref. The ref must be fully qualified. If the given ref does not exist, it is not an error but means that no notes should be printed.
This setting defaults to "refs/notes/commits", and it can be overridden by the GIT_NOTES_REF environment variable. See the section called “git-notes(1)”.
Specify an external helper to be called when a username or password credential is needed; the helper may consult external storage to avoid prompting the user for the credentials. This is normally the name of a credential helper with possible arguments, but may also be an absolute path with arguments or, if preceded by !, shell commands.
Note that multiple helpers may be defined. See the section called “gitcredentials(7)” for details and examples.
A comma separated list of --dirstat parameters specifying the default behavior of the --dirstat option to the section called “git-diff(1)” and friends. The defaults can be overridden on the command line (using --dirstat=<param>,...). The fallback defaults (when not changed by diff.dirstat) are changes,noncumulative,3. The following parameters are available:
Example: The following will count changed files, while ignoring directories with less than 10% of the total amount of changed files, and accumulating child directory counts in the parent directories: files,10,cumulative.
If set, git diff uses a prefix pair that is different from the standard a/ and b/ depending on what is being compared. When this configuration is in effect, reverse diff output also swaps the order of the prefixes:
Choose a diff algorithm. The variants are as follows:
Controls which diff tool is used by the section called “git-difftool(1)” when the -g/--gui flag is specified. This variable overrides the value configured in merge.guitool. The list below shows the valid built-in values. Any other value is treated as a custom diff tool and requires that a corresponding difftool.<guitool>.cmd variable is defined.
Specify the command to invoke the specified diff tool. The specified command is evaluated in shell with the following variables available: LOCAL is set to the name of the temporary file containing the contents of the diff pre-image and REMOTE is set to the name of the temporary file containing the contents of the diff post-image.
See the --tool=<tool> option in the section called “git-difftool(1)” for more details.
Exit difftool if the invoked diff tool returns a non-zero exit status.
See the --trust-exit-code option in the section called “git-difftool(1)” for more details.
Unless otherwise stated, is an error to specify an extension if core.repositoryFormatVersion is not 1. See the section called “gitrepository-layout(5)”.
This extension does not change git's behavior at all. It is useful only for testing format-1 compatibility.
For historical reasons, this extension is respected regardless of the core.repositoryFormatVersion setting.
Specify the hash algorithm to use. The acceptable values are sha1 and sha256. If not specified, sha1 is assumed.
Note that this setting should only be set by the section called “git-init(1)” or the section called “git-clone(1)”. Trying to change it after initialization will not work and will produce hard-to-diagnose issues.
When enabled, indicates that the repo was created with a partial clone (or later performed a partial fetch) and that the remote may have omitted sending certain unwanted objects. Such a remote is called a "promisor remote" and it promises that all such omitted objects can be fetched from it in the future.
The value of this key is the name of the promisor remote.
For historical reasons, this extension is respected regardless of the core.repositoryFormatVersion setting.
If enabled, indicates that objects in the repository MUST NOT be deleted (e.g., by git-prune or git repack -d).
For historical reasons, this extension is respected regardless of the core.repositoryFormatVersion setting.
Specify the ref storage format to use. The acceptable values are:
Note that this setting should only be set by the section called “git-init(1)” or the section called “git-clone(1)”. Trying to change it after initialization will not work and will produce hard-to-diagnose issues.
If enabled, then worktrees will load config settings from the $GIT_DIR/config.worktree file in addition to the $GIT_COMMON_DIR/config file. Note that $GIT_COMMON_DIR and $GIT_DIR are the same for the main working tree, while other working trees have $GIT_DIR equal to $GIT_COMMON_DIR/worktrees/<id>/. The settings in the config.worktree file will override settings from any other config files.
When enabling this extension, you must be careful to move certain values from the common config file to the main working tree's config.worktree file, if present:
It may also be beneficial to adjust the locations of core.sparseCheckout and core.sparseCheckoutCone depending on your desire for customizable sparse-checkout settings for each worktree. By default, the git sparse-checkout builtin enables this extension, assigns these config values on a per-worktree basis, and uses the $GIT_DIR/info/sparse-checkout file to specify the sparsity for each worktree independently. See the section called “git-sparse-checkout(1)” for more details.
For historical reasons, this extension is respected regardless of the core.repositoryFormatVersion setting.
Enable config options that are new to Git, and are being considered for future defaults. Config settings included here may be added or removed with each release, including minor version updates. These settings may have unintended interactions since they are so new. Please enable this setting if you are interested in providing feedback on experimental features. The new default values are:
Enable config options that optimize for repos with many files in the working directory. With many files, commands such as git status and git checkout may be slow and these new defaults improve performance:
Control how information about the commits in the local repository is sent when negotiating the contents of the packfile to be sent by the server. Set to "consecutive" to use an algorithm that walks over consecutive commits checking each one. Set to "skipping" to use an algorithm that skips commits in an effort to converge faster, but may result in a larger-than-necessary packfile; or set to "noop" to not send any information at all, which will almost certainly result in a larger-than-necessary packfile, but will skip the negotiation step. Set to "default" to override settings made previously and use the default behaviour. The default is normally "consecutive", but if feature.experimental is true, then the default is "skipping". Unknown values will cause git fetch to error out.
See also the --negotiate-only and --negotiation-tip options to the section called “git-fetch(1)”.
Specifies the maximal number of fetch operations to be run in parallel at a time (submodules, or remotes when the --multiple option of the section called “git-fetch(1)” is in effect).
A value of 0 will give some reasonable default. If unset, it defaults to 1.
For submodules, this setting can be overridden using the submodule.fetchJobs config setting.
This value stores a URI for downloading Git object data from a bundle URI before performing an incremental fetch from the origin Git server. This is similar to how the --bundle-uri option behaves in the section called “git-clone(1)”. git clone --bundle-uri will set the fetch.bundleURI value if the supplied bundle URI contains a bundle list that is organized for incremental fetches.
If you modify this value and your repository has a fetch.bundleCreationToken value, then remove that fetch.bundleCreationToken value before fetching from the new bundle URI.
When using fetch.bundleURI to fetch incrementally from a bundle list that uses the "creationToken" heuristic, this config value stores the maximum creationToken value of the downloaded bundles. This value is used to prevent downloading bundles in the future if the advertised creationToken is not strictly larger than this value.
The creation token values are chosen by the provider serving the specific bundle URI. If you modify the URI at fetch.bundleURI, then be sure to remove the value for the fetch.bundleCreationToken value before fetching.
Provides the default value for the --notes option to format-patch. Accepts a boolean value, or a ref which specifies where to get notes. If false, format-patch defaults to --no-notes. If true, format-patch defaults to --notes. If set to a non-boolean value, format-patch defaults to --notes=<ref>, where ref is the non-boolean value. Defaults to false.
If one wishes to use the ref refs/notes/true, please use that literal instead.
This configuration can be specified multiple times in order to allow multiple notes refs to be included. In that case, it will behave similarly to multiple --[no-]notes[=] options passed in. That is, a value of true will show the default notes, a value of <ref> will also show notes from that notes ref and a value of false will negate previous configurations and not show notes.
For example,
[format]
notes = true
notes = foo
notes = false
notes = barwill only show notes from refs/notes/bar.
During fsck git may find issues with legacy data which wouldn't be generated by current versions of git, and which wouldn't be sent over the wire if transfer.fsckObjects was set. This feature is intended to support working with legacy repositories containing such data.
Setting fsck.<msg-id> will be picked up by the section called “git-fsck(1)”, but to accept pushes of such data set receive.fsck.<msg-id> instead, or to clone or fetch it set fetch.fsck.<msg-id>.
The rest of the documentation discusses fsck.* for brevity, but the same applies for the corresponding receive.fsck.* and fetch.fsck.*. variables.
Unlike variables like color.ui and core.editor, the receive.fsck.<msg-id> and fetch.fsck.<msg-id> variables will not fall back on the fsck.<msg-id> configuration if they aren't set. To uniformly configure the same fsck settings in different circumstances, all three of them must be set to the same values.
When fsck.<msg-id> is set, errors can be switched to warnings and vice versa by configuring the fsck.<msg-id> setting where the <msg-id> is the fsck message ID and the value is one of error, warn or ignore. For convenience, fsck prefixes the error/warning with the message ID, e.g. "missingEmail: invalid author/committer line - missing email" means that setting fsck.missingEmail = ignore will hide that issue.
In general, it is better to enumerate existing objects with problems with fsck.skipList, instead of listing the kind of breakages these problematic objects share to be ignored, as doing the latter will allow new instances of the same breakages go unnoticed.
Setting an unknown fsck.<msg-id> value will cause fsck to die, but doing the same for receive.fsck.<msg-id> and fetch.fsck.<msg-id> will only cause git to warn.
See the Fsck Messages section of the section called “git-fsck(1)” for supported values of <msg-id>.
The path to a list of object names (i.e. one unabbreviated SHA-1 per line) that are known to be broken in a non-fatal way and should be ignored. On versions of Git 2.20 and later, comments (#), empty lines, and any leading and trailing whitespace are ignored. Everything but a SHA-1 per line will error out on older versions.
This feature is useful when an established project should be accepted despite early commits containing errors that can be safely ignored, such as invalid committer email addresses. Note: corrupt objects cannot be skipped with this setting.
Like fsck.<msg-id> this variable has corresponding receive.fsck.skipList and fetch.fsck.skipList variants.
Unlike variables like color.ui and core.editor the receive.fsck.skipList and fetch.fsck.skipList variables will not fall back on the fsck.skipList configuration if they aren't set. To uniformly configure the same fsck settings in different circumstances, all three of them must be set to the same values.
Older versions of Git (before 2.20) documented that the object names list should be sorted. This was never a requirement; the object names could appear in any order, but when reading the list we tracked whether the list was sorted for the purposes of an internal binary search implementation, which could save itself some work with an already sorted list. Unless you had a humongous list there was no reason to go out of your way to pre-sort the list. After Git version 2.20 a hash implementation is used instead, so there's now no reason to pre-sort the list.
The depth parameter used in the delta compression algorithm used by git gc --aggressive. This defaults to 50, which is the default for the --depth option when --aggressive isn't in use.
See the documentation for the --depth option in the section called “git-repack(1)” for more details.
The window size parameter used in the delta compression algorithm used by git gc --aggressive. This defaults to 250, which is a much more aggressive window size than the default --window of 10.
See the documentation for the --window option in the section called “git-repack(1)” for more details.
When there are approximately more than this many loose objects in the repository, git gc --auto will pack them. Some Porcelain commands use this command to perform a light-weight garbage collection from time to time. The default value is 6700.
Setting this to 0 disables not only automatic packing based on the number of loose objects, but also any other heuristic git gc --auto will otherwise use to determine if there's work to do, such as gc.autoPackLimit.
When there are more than this many packs that are not marked with *.keep file in the repository, git gc --auto consolidates them into one larger pack. The default value is 50. Setting this to 0 disables it. Setting gc.auto to 0 will also disable this.
See the gc.bigPackThreshold configuration variable below. When in use, it'll affect how the auto pack limit works.
If non-zero, all non-cruft packs larger than this limit are kept when git gc is run. This is very similar to --keep-largest-pack except that all non-cruft packs that meet the threshold are kept, not just the largest pack. Defaults to zero. Common unit suffixes of k, m, or g are supported.
Note that if the number of kept packs is more than gc.autoPackLimit, this configuration variable is ignored, all packs except the base pack will be repacked. After this the number of packs should go below gc.autoPackLimit and gc.bigPackThreshold should be respected again.
If the amount of memory estimated for git repack to run smoothly is not available and gc.bigPackThreshold is not set, the largest pack will also be excluded (this is the equivalent of running git gc with --keep-largest-pack).
git reflog expire removes reflog entries older than this time and are not reachable from the current tip; defaults to 30 days. The value "now" expires all entries immediately, and "never" suppresses expiration altogether. With "<pattern>" (e.g. "refs/stash") in the middle, the setting applies only to the refs that match the <pattern>.
These types of entries are generally created as a result of using git commit --amend or git rebase and are the commits prior to the amend or rebase occurring. Since these changes are not part of the current project most users will want to expire them sooner, which is why the default is more aggressive than gc.reflogExpire.
When considering whether or not to remove an object (either when generating a cruft pack or storing unreachable objects as loose), use the shell to execute the specified command(s). Interpret their output as object IDs which Git will consider as "recent", regardless of their age. By treating their mtimes as "now", any objects (and their descendants) mentioned in the output will be kept regardless of their true age.
Output must contain exactly one hex object ID per line, and nothing else. Objects which cannot be found in the repository are ignored. Multiple hooks are supported, but all must exit successfully, else the operation (either generating a cruft pack or unpacking unreachable objects) will be halted.
All gitcvs variables except for gitcvs.usecrlfattr and gitcvs.allBinary can also be specified as gitcvs.<access_method>.<varname> (where access_method is one of "ext" and "pserver") to make them apply only for the given access method.
Specifies which key format to use when signing with --gpg-sign. Default is "openpgp". Other possible values are "x509", "ssh".
See the section called “gitformat-signature(5)” for the signature format, which differs based on the selected gpg.format.
Specifies a minimum trust level for signature verification. If this option is unset, then signature verification for merge operations requires a key with at least marginal trust. Other operations that perform signature verification require a key with at least undefined trust. Setting this option overrides the required trust-level for all operations. Supported values, in increasing order of significance:
A file containing ssh public keys which you are willing to trust. The file consists of one or more lines of principals followed by an ssh public key. e.g.: user1@example.com,user2@example.com ssh-rsa AAAAX1... See ssh-keygen(1) "ALLOWED SIGNERS" for details. The principal is only used to identify the key and is available when verifying a signature.
SSH has no concept of trust levels like gpg does. To be able to differentiate between valid signatures and trusted signatures the trust level of a signature verification is set to fully when the public key is present in the allowedSignersFile. Otherwise the trust level is undefined and git verify-commit/tag will fail.
This file can be set to a location outside of the repository and every developer maintains their own trust store. A central repository server could generate this file automatically from ssh keys with push access to verify the code against. In a corporate setting this file is probably generated at a global location from automation that already handles developer ssh keys.
A repository that only allows signed commits can store the file in the repository itself using a path relative to the top-level of the working tree. This way only committers with an already valid key can add or change keys in the keyring.
Since OpensSSH 8.8 this file allows specifying a key lifetime using valid-after & valid-before options. Git will mark signatures as valid if the signing key was valid at the time of the signature's creation. This allows users to change a signing key without invalidating all previously made signatures.
Using a SSH CA key with the cert-authority option (see ssh-keygen(1) "CERTIFICATES") is also valid.
If git detects typos and can identify exactly one valid command similar to the error, git will try to suggest the correct command or even run the suggestion automatically. Possible config values are:
Override the HTTP proxy, normally configured using the http_proxy, https_proxy, and all_proxy environment variables (see curl(1)). In addition to the syntax understood by curl, it is possible to specify a proxy string with a user name but no password, in which case git will attempt to acquire one in the same way it does for other credentials. See the section called “gitcredentials(7)” for more information. The syntax thus is [protocol://][user[:password]@]proxyhost[:port][/path]. This can be overridden on a per-remote basis; see remote.<name>.proxy
Any proxy, however configured, must be completely transparent and must not modify, transform, or buffer the request or response in any way. Proxies which are not completely transparent are known to cause various forms of breakage with Git.
Set the method with which to authenticate against the HTTP proxy. This only takes effect if the configured proxy string contains a user name part (i.e. is of the form user@host or user@host:port). This can be overridden on a per-remote basis; see remote.<name>.proxyAuthMethod. Both can be overridden by the GIT_HTTP_PROXY_AUTHMETHOD environment variable. Possible values are:
Attempt authentication without first making an unauthenticated attempt and receiving a 401 response. This can be used to ensure that all requests are authenticated. If http.emptyAuth is set to true, this value has no effect.
If the credential helper used specifies an authentication scheme (i.e., via the authtype field), that value will be used; if a username and password is provided without a scheme, then Basic authentication is used. The value of the option determines the scheme requested from the helper. Possible values are:
Note that TLS should always be used with this configuration, since otherwise it is easy to accidentally expose plaintext credentials if Basic authentication is selected.
Control GSSAPI credential delegation. The delegation is disabled by default in libcurl since version 7.21.7. Set parameter to tell the server what it is allowed to delegate when it comes to user credentials. Used with GSS/kerberos. Possible values are:
Use the specified HTTP protocol version when communicating with a server. If you want to force the default. The available and default version depend on libcurl. Currently the possible values of this option are:
Hostname resolution information that will be used first by libcurl when sending HTTP requests. This information should be in one of the following formats:
The first format redirects all requests to the given HOST:PORT to the provided ADDRESS(s). The second format clears all previous config values for that HOST:PORT combination. To allow easy overriding of all the settings inherited from the system config, an empty value will reset all resolution information to the empty list.
The SSL version to use when negotiating an SSL connection, if you want to force the default. The available and default version depend on whether libcurl was built against NSS or OpenSSL and the particular configuration of the crypto library in use. Internally this sets the CURLOPT_SSL_VERSION option; see the libcurl documentation for more details on the format of this option and for the ssl version supported. Currently the possible values of this option are:
Can be overridden by the GIT_SSL_VERSION environment variable. To force git to use libcurl's default ssl version and ignore any explicit http.sslversion option, set GIT_SSL_VERSION to the empty string.
A list of SSL ciphers to use when negotiating an SSL connection. The available ciphers depend on whether libcurl was built against NSS or OpenSSL and the particular configuration of the crypto library in use. Internally this sets the CURLOPT_SSL_CIPHER_LIST option; see the libcurl documentation for more details on the format of this list.
Can be overridden by the GIT_SSL_CIPHER_LIST environment variable. To force git to use libcurl's default cipher list and ignore any explicit http.sslCipherList option, set GIT_SSL_CIPHER_LIST to the empty string.
Maximum size in bytes of the buffer used by smart HTTP transports when POSTing data to the remote system. For requests larger than this buffer size, HTTP/1.1 and Transfer-Encoding: chunked is used to avoid creating a massive pack file locally. Default is 1 MiB, which is sufficient for most requests.
Note that raising this limit is only effective for disabling chunked transfer encoding and therefore should be used only where the remote server or a proxy only supports HTTP/1.0 or is noncompliant with the HTTP standard. Raising this is not, in general, an effective solution for most push problems, but can increase memory consumption significantly since the entire buffer is allocated even for small pushes.
Any of the http.* options above can be applied selectively to some URLs. For a config key to match a URL, each element of the config key is compared to that of the URL, in the following order:
The list above is ordered by decreasing precedence; a URL that matches a config key's path is preferred to one that matches its user name. For example, if the URL is https://user@example.com/foo/bar a config key match of https://example.com/foo will be preferred over a config key match of https://user@example.com.
All URLs are normalized before attempting any matching (the password part, if embedded in the URL, is always ignored for matching purposes) so that equivalent URLs that are simply spelled differently will match properly. Environment variable settings always override any matches. The URLs that are matched against are those given directly to Git commands. This means any URLs visited as a result of a redirection do not participate in matching.
When enabled, do not compute the trailing hash for the index file. This accelerates Git commands that manipulate the index, such as git add, git commit, or git status. Instead of storing the checksum, write a trailing set of bytes with value zero, indicating that the computation was skipped.
If you enable index.skipHash, then Git clients older than 2.13.0 will refuse to parse the index and Git clients older than 2.40.0 will report an error during git fsck.
Set the default date-time mode for the log command. Setting a value for log.date is similar to using git log's --date option. See the section called “git-log(1)” for details.
If the format is set to "auto:foo" and the pager is in use, format "foo" will be used for the date format. Otherwise, "default" will be used.
Many Git commands trigger automatic maintenance after they have written data into the repository. This boolean config option controls whether this automatic maintenance shall happen in the foreground or whether the maintenance process shall detach and continue to run in the background.
If unset, the value of gc.autoDetach is used as a fallback. Defaults to true if both are unset, meaning that the maintenance process will detach.
This string config option provides a way to specify one of a few recommended schedules for background maintenance. This only affects which tasks are run during git maintenance run --schedule=X commands, provided no --task=<task> arguments are provided. Further, if a maintenance.<task>.schedule config value is set, then that value is used instead of the one provided by maintenance.strategy. The possible strategy strings are:
<<<<<<< conflict marker, changes made by one side,
a ======= marker, changes made by the other side, and then
a >>>>>>> marker. An alternate style, "diff3", adds a |||||||
marker and the original text before the ======= marker. The
"merge" style tends to produce smaller conflict regions than diff3,
both because of the exclusion of the original text, and because
when a subset of lines match on the two sides, they are just pulled
out of the conflict region. Another alternate style, "zdiff3", is
similar to diff3 but removes matching lines on the two sides from
the conflict region when those matching lines appear near either
the beginning or end of a conflict region.
By adding a glob that matches the names of integration branches to this multi-valued configuration variable, the default merge message computed for merges into these integration branches will omit "into <branch-name>" from its title.
An element with an empty value can be used to clear the list of globs accumulated from previous configuration entries. When there is no merge.suppressDest variable defined, the default value of master is used for backward compatibility.
Whether Git detects directory renames, affecting what happens at merge time to new files added to a directory on one side of history when that directory was renamed on the other side of history. Possible values are:
If merge.renames is false, merge.directoryRenames is ignored and treated as false. Defaults to conflict.
Controls which merge tool is used by the section called “git-mergetool(1)” when the -g/--gui flag is specified. The list below shows the valid built-in values. Any other value is treated as a custom merge tool and requires that a corresponding mergetool.<guitool>.cmd variable is defined.
Which merge strategy to choose by default when resolving notes conflicts. Must be one of manual, ours, theirs, union, or cat_sort_uniq. Defaults to manual. See the "NOTES MERGE STRATEGIES" section of the section called “git-notes(1)” for more information on each strategy.
This setting can be overridden by passing the --strategy option to the section called “git-notes(1)”.
Which ref (or refs, if a glob or specified more than once), in addition to the default set by core.notesRef or GIT_NOTES_REF, to read notes from when showing commit messages with the git log family of commands.
This setting can be overridden with the GIT_NOTES_DISPLAY_REF environment variable, which must be a colon separated list of refs or globs.
A warning will be issued for refs that do not exist, but a glob that does not match any refs is silently ignored.
This setting can be disabled by the --no-notes option to the the section called “git-log(1)” family of commands, or by the --notes=<ref> option accepted by those commands.
The effective value of core.notesRef (possibly overridden by GIT_NOTES_REF) is also implicitly added to the list of refs to be displayed.
When rewriting commits with <command> (currently amend or rebase), if this variable is false, git will not copy notes from the original to the rewritten commit. Defaults to true. See also notes.rewriteRef below.
This setting can be overridden with the GIT_NOTES_REWRITE_REF environment variable, which must be a colon separated list of refs or globs.
When copying notes during a rewrite (see the notes.rewrite.<command> option), determines what to do if the target commit already has a note. Must be one of overwrite, concatenate, cat_sort_uniq, or ignore. Defaults to concatenate.
This setting can be overridden with the GIT_NOTES_REWRITE_MODE environment variable.
When copying notes during a rewrite, specifies the (fully qualified) ref whose notes should be copied. May be a glob, in which case notes in all matching refs will be copied. You may also specify this configuration several times.
Does not have a default value; you must configure this variable to enable note rewriting. Set it to refs/notes/commits to enable rewriting for the default commit notes.
Can be overridden with the GIT_NOTES_REWRITE_REF environment variable. See notes.rewrite.<command> above for a further description of its format.
An integer -1..9, indicating the compression level for objects in a pack file. -1 is the zlib default. 0 means no compression, and 1..9 are various speed/size tradeoffs, 9 being slowest. If not set, defaults to core.compression. If that is not set, defaults to -1, the zlib default, which is "a default compromise between speed and compression (currently equivalent to level 6)."
Note that changing the compression level will not automatically recompress all existing objects. You can force recompression by passing the -F option to the section called “git-repack(1)”.
When true or "single", and when reachability bitmaps are enabled, pack-objects will try to send parts of the bitmapped packfile verbatim. When "multi", and when a multi-pack reachability bitmap is available, pack-objects will try to send parts of all packs in the MIDX.
If only a single pack bitmap is available, and pack.allowPackReuse is set to "multi", reuse parts of just the bitmapped packfile. This can reduce memory and CPU usage to serve fetches, but might result in sending a slightly larger pack. Defaults to true.
Specify the default pack index version. Valid values are 1 for legacy pack index used by Git versions prior to 1.5.2, and 2 for the new pack index with capabilities for packs larger than 4 GB as well as proper protection against the repacking of corrupted packs. Version 2 is the default. Note that version 2 is enforced and this config option is ignored whenever the corresponding pack is larger than 2 GB.
If you have an old Git that does not understand the version 2 *.idx file, cloning or fetching over a non-native protocol (e.g. "http") that will copy both *.pack file and corresponding *.idx file from the other side may give you a repository that cannot be accessed with your older version of Git. If the *.pack file is smaller than 2 GB, however, you can use the section called “git-index-pack(1)” on the *.pack file to regenerate the *.idx file.
The maximum size of a pack. This setting only affects packing to a file when repacking, i.e. the git:// protocol is unaffected. It can be overridden by the --max-pack-size option of the section called “git-repack(1)”. Reaching this limit results in the creation of multiple packfiles.
Note that this option is rarely useful, and may result in a larger total on-disk size (because Git will not store deltas between packs) and worse runtime performance (object lookup within multiple packs is slower than a single pack, and optimizations like reachability bitmaps cannot cope with multiple packs).
If you need to actively run Git using smaller packfiles (e.g., because your filesystem does not support large files), this option may help. But if your goal is to transmit a packfile over a medium that supports limited sizes (e.g., removable media that cannot store the whole repository), you are likely better off creating a single large packfile and splitting it using a generic multi-volume archive tool (e.g., Unix split).
The minimum size allowed is limited to 1 MiB. The default is unlimited. Common unit suffixes of k, m, or g are supported.
When true, Git will use an experimental algorithm for computing reachability queries with bitmaps. Instead of building up complete bitmaps for all of the negated tips and then OR-ing them together, consider negated tips with existing bitmaps as additive (i.e. OR-ing them into the result if they exist, ignoring them otherwise), and build up a bitmap at the boundary instead.
When using this algorithm, Git may include too many objects as a result of not opening up trees belonging to certain UNINTERESTING commits. This inexactness matches the non-bitmap traversal algorithm.
In many cases, this can provide a speed-up over the exact algorithm, particularly when there is poor bitmap coverage of the negated side of the query.
When selecting which commits will receive bitmaps, prefer a commit at the tip of any reference that is a suffix of any value of this configuration over any other commits in the "selection window".
Note that setting this configuration to refs/foo does not mean that the commits at the tips of refs/foo/bar and refs/foo/baz will necessarily be selected. This is because commits are selected for bitmaps from within a series of windows of variable length.
If a commit at the tip of any reference which is a suffix of any value of this configuration is seen in a window, it is immediately given preference over any other commit in that window.
When true, git will include a "hash cache" section in the bitmap index (if one is written). This cache can be used to feed git's delta heuristics, potentially leading to better deltas between bitmapped and non-bitmapped objects (e.g., when serving a fetch between an older, bitmapped pack and objects that have been pushed since the last gc). The downside is that it consumes 4 bytes per object of disk space. Defaults to true.
When writing a multi-pack reachability bitmap, no new namehashes are computed; instead, any namehashes stored in an existing bitmap are permuted into their appropriate location when writing a new bitmap.
If set, provide a user defined default policy for all protocols which don't explicitly have a policy (protocol.<name>.allow). By default, if unset, known-safe protocols (http, https, git, ssh) have a default policy of always, known-dangerous protocols (ext) have a default policy of never, and all other protocols (including file) have a default policy of user. Supported policies:
Set a policy to be used by protocol <name> with clone/fetch/push commands. See protocol.allow above for the available policies.
The protocol names currently used by git are:
If set, clients will attempt to communicate with a server using the specified protocol version. If the server does not support it, communication falls back to version 0. If unset, the default is 2. Supported versions:
When true, rebase branches on top of the fetched branch, instead of merging the default branch from the default remote when "git pull" is run. See "branch.<name>.rebase" for setting this on a per-branch basis.
When merges (or just m), pass the --rebase-merges option to git rebase so that the local merge commits are included in the rebase (see the section called “git-rebase(1)” for details).
When the value is interactive (or just i), the rebase is run in interactive mode.
NOTE: this is a possibly dangerous operation; do not use it unless you understand the implications (see the section called “git-rebase(1)” for details).
Defines the action git push should take if no refspec is given (whether from the command-line, config, or elsewhere). Different values are well-suited for specific workflows; for instance, in a purely central workflow (i.e. the fetch source is equal to the push destination), upstream is probably what you want. Possible values are:
simple - push the current branch with the same name on the remote.
If you are working on a centralized workflow (pushing to the same repository you pull from, which is typically origin), then you need to configure an upstream branch with the same name.
This mode is the default since Git 2.0, and is the safest option suited for beginners.
matching - push all branches having the same name on both ends. This makes the repository you are pushing to remember the set of branches that will be pushed out (e.g. if you always push maint and master there and no other branches, the repository you push to will have these two branches, and your local maint and master will be pushed there).
To use this mode effectively, you have to make sure all the branches you would push out are ready to be pushed out before running git push, as the whole point of this mode is to allow you to push all of the branches in one go. If you usually finish work on only one branch and push out the result, while other branches are unfinished, this mode is not for you. Also this mode is not suitable for pushing into a shared central repository, as other people may add new branches there, or update the tip of existing branches outside your control.
This used to be the default, but not since Git 2.0 (simple is the new default).
When no --push-option=<option> argument is given from the command line, git push behaves as if each <value> of this variable is given as --push-option=<value>.
This is a multi-valued variable, and an empty value can be used in a higher priority configuration file (e.g. .git/config in a repository) to clear the values inherited from a lower priority configuration files (e.g. $HOME/.gitconfig).
Example: /etc/gitconfig push.pushoption = a push.pushoption = b ~/.gitconfig push.pushoption = c repo/.git/config push.pushoption = push.pushoption = b This will result in only b (a and c are cleared).
If set to true, git rebase will use abbreviated command names in the todo list resulting in something like this:
p deadbee The oneline of the commit
p fa1afe1 The oneline of the next commit
...instead of:
pick deadbee The oneline of the commit
pick fa1afe1 The oneline of the next commit
...Defaults to false.
If set to true or "refuse", git-receive-pack will deny a ref update to the currently checked out branch of a non-bare repository. Such a push is potentially dangerous because it brings the HEAD out of sync with the index and working tree. If set to "warn", print a warning of such a push to stderr, but allow the push to proceed. If set to false or "ignore", allow such pushes with no message. Defaults to "refuse".
Another option is "updateInstead" which will update the working tree if pushing into the current branch. This option is intended for synchronizing working directories when one side is not easily accessible via interactive ssh (e.g. a live web site, hence the requirement that the working directory be clean). This mode also comes in handy when developing inside a VM to test and fix code on different Operating Systems.
By default, "updateInstead" will refuse the push if the working tree or the index have any difference from the HEAD, but the push-to-checkout hook can be used to customize this. See the section called “githooks(5)”.
This is a multi-valued variable that defines reference prefixes to match the commands in receive-pack. Commands matching the prefixes will be executed by an external hook "proc-receive", instead of the internal execute_commands function. If this variable is not defined, the "proc-receive" hook will never be used, and all commands will be executed by the internal execute_commands function.
For example, if this variable is set to "refs/for", pushing to reference such as "refs/for/master" will not create or update a reference named "refs/for/master", but may create or update a pull request directly by running the hook "proc-receive".
Optional modifiers can be provided in the beginning of the value to filter commands for specific actions: create (a), modify (m), delete (d). A ! can be included in the modifiers to negate the reference prefix entry. E.g.:
git config --system --add receive.procReceiveRefs ad:refs/heads git config --system --add receive.procReceiveRefs !:refs/heads
The size in bytes used by the reftable backend when writing blocks. The block size is determined by the writer, and does not have to be a power of 2. The block size must be larger than the longest reference name or log entry used in the repository, as references cannot span blocks.
Powers of two that are friendly to the virtual memory system or filesystem (such as 4kB or 8kB) are recommended. Larger sizes (64kB) can yield better compression, with a possible increased cost incurred by readers during access.
The largest block size is 16777215 bytes (15.99 MiB). The default value is 4096 bytes (4kB). A value of 0 will use the default value.
The interval at which to create restart points. The reftable backend determines the restart points at file creation. Every 16 may be more suitable for smaller block sizes (4k or 8k), every 64 for larger block sizes (64k).
More frequent restart points reduces prefix compression and increases space consumed by the restart table, both of which increase file size.
Less frequent restart points makes prefix compression more effective, decreasing overall file size, with increased penalties for readers walking through more records after the binary search step.
A maximum of 65535 restart points per block is supported.
The default value is to create restart points every 16 records. A value of 0 will use the default value.
Whether the reftable backend shall write object blocks. Object blocks are a reverse mapping of object ID to the references pointing to them.
The default value is true.
Whenever the reftable backend appends a new table to the stack, it performs auto compaction to ensure that there is only a handful of tables. The backend does this by ensuring that tables form a geometric sequence regarding the respective sizes of each table.
By default, the geometric sequence uses a factor of 2, meaning that for any table, the next-biggest table must at least be twice as big. A maximum factor of 256 is supported.
When set to true, fetching from this remote by default will also remove any local tags that no longer exist on the remote if pruning is activated in general via remote.<name>.prune, fetch.prune or --prune. Overrides fetch.pruneTags settings, if any.
See also remote.<name>.prune and the PRUNING section of the section called “git-fetch(1)”.
The default set of server options used when fetching from this remote. These server options can be overridden by the --server-option= command line arguments.
This is a multi-valued variable, and an empty value can be used in a higher priority configuration file (e.g. .git/config in a repository) to clear the values inherited from a lower priority configuration files (e.g. $HOME/.gitconfig).
Specifies which bare repositories Git will work with. The currently supported values are:
explicit: Git only works with bare repositories specified via the top-level --git-dir command-line option, or the GIT_DIR environment variable (see the section called “git(1)”).
If you do not use bare repositories in your workflow, then it may be beneficial to set safe.bareRepository to explicit in your global config. This will protect you from attacks that involve cloning a repository that contains a bare repository and running a Git command within that directory.
This config setting is only respected in protected configuration (see the section called “SCOPES”). This prevents untrusted repositories from tampering with this value.
These config entries specify Git-tracked directories that are considered safe even if they are owned by someone other than the current user. By default, Git will refuse to even parse a Git config of a repository owned by someone else, let alone run its hooks, and this config setting allows users to specify exceptions, e.g. for intentionally shared repositories (see the --shared option in the section called “git-init(1)”).
This is a multi-valued setting, i.e. you can add more than one directory via git config --add. To reset the list of safe directories (e.g. to override any such directories specified in the system config), add a safe.directory entry with an empty value.
This config setting is only respected in protected configuration (see the section called “SCOPES”). This prevents untrusted repositories from tampering with this value.
The value of this setting is interpolated, i.e. ~/<path> expands to a path relative to the home directory and %(prefix)/<path> expands to a path relative to Git's (runtime) prefix.
To completely opt-out of this security check, set safe.directory to the string *. This will allow all repositories to be treated as if their directory was listed in the safe.directory list. If safe.directory=* is set in system config and you want to re-enable this protection, then initialize your list with an empty value before listing the repositories that you deem safe. Giving a directory with /* appended to it will allow access to all repositories under the named directory.
As explained, Git only allows you to access repositories owned by yourself, i.e. the user who is running Git, by default. When Git is running as root in a non Windows platform that provides sudo, however, git checks the SUDO_UID environment variable that sudo creates and will allow access to the uid recorded as its value in addition to the id from root. This is to make it easy to perform a common sequence during installation "make && sudo make install". A git process running under sudo runs as root but the sudo command exports the environment variable to record which id the original user has. If that is not what you would prefer and want git to only trust repositories that are owned by root instead, then you can remove the SUDO_UID variable from root's environment before invoking git.
Format of the file(s) specified in sendemail.aliasesFile. Must be one of mutt, mailrc, pine, elm, gnus, or sendmail.
What an alias file in each format looks like can be found in the documentation of the email program of the same name. The differences and limitations from the standard formats are described below:
Typically with sparse checkouts, files not matching any sparsity patterns are marked with a SKIP_WORKTREE bit in the index and are missing from the working tree. Accordingly, Git will ordinarily check whether files with the SKIP_WORKTREE bit are in fact present in the working tree contrary to expectations. If Git finds any, it marks those paths as present by clearing the relevant SKIP_WORKTREE bits. This option can be used to tell Git that such present-despite-skipped files are expected and to stop checking for them.
The default is false, which allows Git to automatically recover from the list of files in the index and working tree falling out of sync.
Set this to true if you are in a setup where some external factor relieves Git of the responsibility for maintaining the consistency between the presence of working tree files and sparsity patterns. For example, if you have a Git-aware virtual file system that has a robust mechanism for keeping the working tree and the sparsity patterns up to date based on access patterns.
Regardless of this setting, Git does not check for present-despite-skipped files unless sparse checkout is enabled, so this config option has no effect unless core.sparseCheckout is true.
By default, Git determines the command line arguments to use based on the basename of the configured SSH command (configured using the environment variable GIT_SSH or GIT_SSH_COMMAND or the config setting core.sshCommand). If the basename is unrecognized, Git will attempt to detect support of OpenSSH options by first invoking the configured SSH command with the -G (print configuration) option and will subsequently use OpenSSH options (if that is successful) or no options besides the host and remote command (if it fails).
The config variable ssh.variant can be set to override this detection. Valid values are ssh (to use OpenSSH options), plink, putty, tortoiseplink, simple (no options except the host and remote command). The default auto-detection can be explicitly requested using the value auto. Any other value is treated as ssh. This setting can also be overridden via the environment variable GIT_SSH_VARIANT.
The current command-line parameters used for each variant are as follows:
Except for the simple variant, command-line parameters are likely to change as git gains new features.
By default, the section called “git-status(1)” and the section called “git-commit(1)” show files which are not currently tracked by Git. Directories which contain only untracked files, are shown with the directory name only. Showing untracked files means that Git needs to lstat() all the files in the whole repository, which might be slow on some systems. So, this variable controls how the commands display the untracked files. Possible values are:
If this variable is not specified, it defaults to normal. All usual spellings for Boolean value true are taken as normal and false as no. This variable can be overridden with the -u|--untracked-files option of the section called “git-status(1)” and the section called “git-commit(1)”.
A boolean indicating if commands should enable the --recurse-submodules option by default. Defaults to false.
When set to true, it can be deactivated via the --no-recurse-submodules option. Note that some Git commands lacking this option may call some of the above commands affected by submodule.recurse; for instance git remote update will call git fetch but does not have a --no-recurse-submodules option. For these commands a workaround is to temporarily change the configuration value by using git -c submodule.recurse=0.
The following list shows the commands that accept --recurse-submodules and whether they are supported by this setting.
Trace2 config settings are only read from the system and global config files; repository local and worktree config files and -c command line arguments are not respected.
This variable controls the event target destination. It may be overridden by the GIT_TRACE2_EVENT environment variable. The following table shows possible values.
This option tells which characters are recognized as trailer separators. By default only : is recognized as a trailer separator, except that = is always accepted on the command line for compatibility with other git commands.
The first character given by this option will be the default character used when another separator is not specified in the config for this trailer.
For example, if the value for this option is "%=$", then only lines using the format <key><sep><value> with <sep> containing %, = or $ and then spaces will be considered trailers. And % will be the default separator used, so by default trailers will appear like: <key>% <value> (one percent sign and one space will appear between the key and the value).
This option tells where a new trailer will be added.
This can be end, which is the default, start, after or before.
If it is end, then each new trailer will appear at the end of the existing trailers.
If it is start, then each new trailer will appear at the start, instead of the end, of the existing trailers.
If it is after, then each new trailer will appear just after the last trailer with the same <key>.
If it is before, then each new trailer will appear just before the first trailer with the same <key>.
This option makes it possible to choose what action will be performed when there is already at least one trailer with the same <key> in the input.
The valid values for this option are: addIfDifferentNeighbor (this is the default), addIfDifferent, add, replace or doNothing.
With addIfDifferentNeighbor, a new trailer will be added only if no trailer with the same (<key>, <value>) pair is above or below the line where the new trailer will be added.
With addIfDifferent, a new trailer will be added only if no trailer with the same (<key>, <value>) pair is already in the input.
With add, a new trailer will be added, even if some trailers with the same (<key>, <value>) pair are already in the input.
With replace, an existing trailer with the same <key> will be deleted and the new trailer will be added. The deleted trailer will be the closest one (with the same <key>) to the place where the new one will be added.
With doNothing, nothing will be done; that is no new trailer will be added if there is already one with the same <key> in the input.
This option makes it possible to choose what action will be performed when there is not yet any trailer with the same <key> in the input.
The valid values for this option are: add (this is the default) and doNothing.
With add, a new trailer will be added.
With doNothing, nothing will be done.
Defines a <keyAlias> for the <key>. The <keyAlias> must be a prefix (case does not matter) of the <key>. For example, in git config trailer.ack.key "Acked-by" the "Acked-by" is the <key> and the "ack" is the <keyAlias>. This configuration allows the shorter --trailer "ack:..." invocation on the command line using the "ack" <keyAlias> instead of the longer --trailer "Acked-by:...".
At the end of the <key>, a separator can appear and then some space characters. By default the only valid separator is :, but this can be changed using the trailer.separators config variable.
If there is a separator in the key, then it overrides the default separator when adding the trailer.
Deprecated in favor of trailer.<keyAlias>.cmd. This option behaves in the same way as trailer.<keyAlias>.cmd, except that it doesn't pass anything as argument to the specified command. Instead the first occurrence of substring $ARG is replaced by the <value> that would be passed as argument.
Note that $ARG in the user's command is only replaced once and that the original way of replacing $ARG is not safe.
When both trailer.<keyAlias>.cmd and trailer.<keyAlias>.command are given for the same <keyAlias>, trailer.<keyAlias>.cmd is used and trailer.<keyAlias>.command is ignored.
This option can be used to specify a shell command that will be called once to automatically add a trailer with the specified <keyAlias>, and then called each time a --trailer <keyAlias>=<value> argument is specified to modify the <value> of the trailer that this option would produce.
When the specified command is first called to add a trailer with the specified <keyAlias>, the behavior is as if a special --trailer <keyAlias>=<value> argument was added at the beginning of the "git interpret-trailers" command, where <value> is taken to be the standard output of the command with any leading and trailing whitespace trimmed off.
If some --trailer <keyAlias>=<value> arguments are also passed on the command line, the command is called again once for each of these arguments with the same <keyAlias>. And the <value> part of these arguments, if any, will be passed to the command as its first argument. This way the command can produce a <value> computed from the <value> passed in the --trailer <keyAlias>=<value> argument.
A configured URL can contain plaintext credentials in the form <protocol>://<user>:<password>@<domain>/<path>. You may want to warn or forbid the use of such configuration (in favor of using the section called “git-credential(1)”). This will be used on the section called “git-clone(1)”, the section called “git-fetch(1)”, the section called “git-push(1)”, and any other direct use of the configured URL.
Note that this is currently limited to detecting credentials in remote.<name>.url configuration; it won't detect credentials in remote.<name>.pushurl configuration.
You might want to enable this to prevent inadvertent credentials exposure, e.g. because:
The git programs will pass the full URL to one another as arguments on the command-line, meaning the credentials will be exposed to other unprivileged users on systems that allow them to see the full process list of other users. On linux the "hidepid" setting documented in procfs(5) allows for configuring this behavior.
If such concerns don't apply to you then you probably don't need to be concerned about credentials exposure due to storing sensitive data in git's configuration files. If you do want to use this, set transfer.credentialsInUrl to one of these values:
When fetch.fsckObjects or receive.fsckObjects are not set, the value of this variable is used instead. Defaults to false.
When set, the fetch or receive will abort in the case of a malformed object or a link to a nonexistent object. In addition, various other issues are checked for, including legacy issues (see fsck.<msg-id>), and potential security issues like the existence of a .GIT directory or a malicious .gitmodules file (see the release notes for v2.2.1 and v2.17.1 for details). Other sanity and security checks may be added in future releases.
On the receiving side, failing fsckObjects will make those objects unreachable, see "QUARANTINE ENVIRONMENT" in the section called “git-receive-pack(1)”. On the fetch side, malformed objects will instead be left unreferenced in the repository.
Due to the non-quarantine nature of the fetch.fsckObjects implementation it cannot be relied upon to leave the object store clean like receive.fsckObjects can.
As objects are unpacked they're written to the object store, so there can be cases where malicious objects get introduced even though the "fetch" failed, only to have a subsequent "fetch" succeed because only new incoming objects are checked, not those that have already been written to the object store. That difference in behavior should not be relied upon. In the future, such objects may be quarantined for "fetch" as well.
For now, the paranoid need to find some way to emulate the quarantine environment if they'd like the same protection as "push". E.g. in the case of an internal mirror do the mirroring in two steps, one to fetch the untrusted objects, and then do a second "push" (which will use the quarantine) to another internal repo, and have internal clients consume this pushed-to repository, or embargo internal fetches and only allow them once a full "fsck" has run (and no new fetches have happened in the meantime).
String(s) receive-pack and upload-pack use to decide which refs to omit from their initial advertisements. Use more than one definition to specify multiple prefix strings. A ref that is under the hierarchies listed in the value of this variable is excluded, and is hidden when responding to git push or git fetch. See receive.hideRefs and uploadpack.hideRefs for program-specific versions of this config.
You may also include a ! in front of the ref name to negate the entry, explicitly exposing it, even if an earlier entry marked it as hidden. If you have multiple hideRefs values, later entries override earlier ones (and entries in more-specific config files override less-specific ones).
If a namespace is in use, the namespace prefix is stripped from each reference before it is matched against transfer.hiderefs patterns. In order to match refs before stripping, add a ^ in front of the ref name. If you combine ! and ^, ! must be specified first.
For example, if refs/heads/master is specified in transfer.hideRefs and the current namespace is foo, then refs/namespaces/foo/refs/heads/master is omitted from the advertisements. If uploadpack.allowRefInWant is set, upload-pack will treat want-ref refs/heads/master in a protocol v2 fetch command as if refs/namespaces/foo/refs/heads/master did not exist. receive-pack, on the other hand, will still advertise the object id the ref is pointing to without mentioning its name (a so-called ".have" line).
Even if you hide refs, a client may still be able to steal the target objects via the techniques described in the "SECURITY" section of the the section called “gitnamespaces(7)” man page; it's best to keep private data in a separate repository.
If this option is set, when upload-pack would run git pack-objects to create a packfile for a client, it will run this shell command instead. The pack-objects command and arguments it would have run (including the git pack-objects at the beginning) are appended to the shell command. The stdin and stdout of the hook are treated as if pack-objects itself was run. I.e., upload-pack will feed input intended for pack-objects to the hook, and expects a completed packfile on stdout.
Note that this configuration variable is only respected when it is specified in protected configuration (see the section called “SCOPES”). This is a safety measure against fetching from untrusted repositories.
Any URL that starts with this value will be rewritten to start, instead, with <base>. In cases where some site serves a large number of repositories, and serves them with multiple access methods, and some users need to use different access methods, this feature allows people to specify any of the equivalent URLs and have Git automatically rewrite the URL to the best alternative for the particular user, even for a never-before-seen repository on the site. When more than one insteadOf strings match a given URL, the longest match is used.
Note that any protocol restrictions will be applied to the rewritten URL. If the rewrite changes the URL to use a custom protocol or remote helper, you may need to adjust the protocol.*.allow config to permit the request. In particular, protocols you expect to use for submodules must be set to always rather than the default of user. See the description of protocol.allow above.
The user.name and user.email variables determine what ends up in the author and committer fields of commit objects. If you need the author or committer to be different, the author.name, author.email, committer.name, or committer.email variables can be set. All of these can be overridden by the GIT_AUTHOR_NAME, GIT_AUTHOR_EMAIL, GIT_COMMITTER_NAME, GIT_COMMITTER_EMAIL, and EMAIL environment variables.
Note that the name forms of these variables conventionally refer to some form of a personal name. See the section called “git-commit(1)” and the environment variables section of the section called “git(1)” for more information on these settings and the credential.username option if you're looking for authentication credentials instead.
Even when version sort is used in the section called “git-tag(1)”, tagnames with the same base version but different suffixes are still sorted lexicographically, resulting e.g. in prerelease tags appearing after the main release (e.g. "1.0-rc1" after "1.0"). This variable can be specified to determine the sorting order of tags with different suffixes.
By specifying a single suffix in this variable, any tagname containing that suffix will appear before the corresponding main release. E.g. if the variable is set to "-rc", then all "1.0-rcX" tags will appear before "1.0". If specified multiple times, once per suffix, then the order of suffixes in the configuration will determine the sorting order of tagnames with those suffixes. E.g. if "-pre" appears before "-rc" in the configuration, then all "1.0-preX" tags will be listed before any "1.0-rcX" tags. The placement of the main release tag relative to tags with various suffixes can be determined by specifying the empty suffix among those other suffixes. E.g. if the suffixes "-rc", "", "-ck", and "-bfs" appear in the configuration in this order, then all "v4.8-rcX" tags are listed first, followed by "v4.8", then "v4.8-ckX" and finally "v4.8-bfsX".
If more than one suffix matches the same tagname, then that tagname will be sorted according to the suffix which starts at the earliest position in the tagname. If more than one different matching suffix starts at that earliest position, then that tagname will be sorted according to the longest of those suffixes. The sorting order between different suffixes is undefined if they are in multiple config files.
Link worktrees using relative paths (when "true") or absolute paths (when "false"). This is particularly useful for setups where the repository and worktrees may be moved between different locations or environments. Defaults to "false".
Note that setting worktree.useRelativePaths to "true" implies enabling the extension.relativeWorktrees config (see the section called “git-config(1)”), thus making it incompatible with older versions of Git.
When using the deprecated [section.subsection] syntax, changing a value will result in adding a multi-line key instead of a change, if the subsection is given with at least one uppercase character. For example when the config looks like
[section.subsection]
key = value1and running git config section.Subsection.key value2 will result in
[section.subsection]
key = value1
key = value2Part of the the section called “git(1)” suite
Counts the number of unpacked object files and disk space consumed by them, to help you decide when it is a good time to repack.
Provide more detailed reports:
count: the number of loose objects
size: disk space consumed by loose objects, in KiB (unless -H is specified)
in-pack: the number of in-pack objects
size-pack: disk space consumed by the packs, in KiB (unless -H is specified)
prune-packable: the number of loose objects that are also present in the packs. These objects could be pruned using git prune-packed.
garbage: the number of files in the object database that are neither valid loose objects nor valid packs
size-garbage: disk space consumed by garbage files, in KiB (unless -H is specified)
alternate: absolute path of alternate object databases; may appear multiple times, one line per path. Note that if the path contains non-printable characters, it may be surrounded by double-quotes and contain C-style backslashed escape sequences.
Part of the the section called “git(1)” suite
Git has an internal interface for storing and retrieving credentials from system-specific helpers, as well as prompting the user for usernames and passwords. The git-credential command exposes this interface to scripts which may want to retrieve, store, or prompt for credentials in the same manner as Git. The design of this scriptable interface models the internal C API; see credential.h for more background on the concepts.
git-credential takes an "action" option on the command-line (one of fill, approve, or reject) and reads a credential description on stdin (see INPUT/OUTPUT FORMAT).
If the action is fill, git-credential will attempt to add "username" and "password" attributes to the description by reading config files, by contacting any configured credential helpers, or by prompting the user. The username and password attributes of the credential description are then printed to stdout together with the attributes already provided.
If the action is approve, git-credential will send the description to any configured credential helpers, which may store the credential for later use.
If the action is reject, git-credential will send the description to any configured credential helpers, which may erase any stored credentials matching the description.
If the action is capability, git-credential will announce any capabilities it supports to standard output.
If the action is approve or reject, no output should be emitted.
An application using git-credential will typically use git credential following these steps:
Generate a credential description based on the context.
For example, if we want a password for https://example.com/foo.git, we might generate the following credential description (don't forget the blank line at the end; it tells git credential that the application finished feeding all the information it has):
protocol=https host=example.com path=foo.git
Ask git-credential to give us a username and password for this description. This is done by running git credential fill, feeding the description from step (1) to its standard input. The complete credential description (including the credential per se, i.e. the login and password) will be produced on standard output, like:
protocol=https host=example.com username=bob password=secr3t
In most cases, this means the attributes given in the input will be repeated in the output, but Git may also modify the credential description, for example by removing the path attribute when the protocol is HTTP(s) and credential.useHttpPath is false.
If the git credential knew about the password, this step may not have involved the user actually typing this password (the user may have typed a password to unlock the keychain instead, or no user interaction was done if the keychain was already unlocked) before it returned password=secr3t.
git credential reads and/or writes (depending on the action used) credential information in its standard input/output. This information can correspond either to keys for which git credential will obtain the login information (e.g. host, protocol, path), or to the actual credential data to be obtained (username/password).
The credential is split into a set of named attributes, with one attribute per line. Each attribute is specified by a key-value pair, separated by an = (equals) sign, followed by a newline.
The key may contain any bytes except =, newline, or NUL. The value may contain any bytes except newline or NUL. A line, including the trailing newline, may not exceed 65535 bytes in order to allow implementations to parse efficiently.
Attributes with keys that end with C-style array brackets [] can have multiple values. Each instance of a multi-valued attribute forms an ordered list of values - the order of the repeated attributes defines the order of the values. An empty multi-valued attribute (key[]=\n) acts to clear any previous entries and reset the list.
In all cases, all bytes are treated as-is (i.e., there is no quoting, and one cannot transmit a value with newline or NUL in it). The list of attributes is terminated by a blank line or end-of-file.
Git understands the following attributes:
When this special attribute is read by git credential, the value is parsed as a URL and treated as if its constituent parts were read (e.g., url=https://example.com would behave as if protocol=https and host=example.com had been provided). This can help callers avoid parsing URLs themselves.
Note that specifying a protocol is mandatory and if the URL doesn't specify a hostname (e.g., "cert:///path/to/file") the credential will contain a hostname attribute whose value is an empty string.
Components which are missing from the URL (e.g., there is no username in the example above) will be left unset.
This indicates that the authentication scheme in question should be used. Common values for HTTP and HTTPS include basic, bearer, and digest, although the latter is insecure and should not be used. If credential is used, this may be set to an arbitrary string suitable for the protocol in question (usually HTTP).
This value should not be sent unless the appropriate capability (see below) is provided on input.
The pre-encoded credential, suitable for the protocol in question (usually HTTP). If this key is sent, authtype is mandatory, and username and password are not used. For HTTP, Git concatenates the authtype value and this value with a single space to determine the Authorization header.
This value should not be sent unless the appropriate capability (see below) is provided on input.
This boolean value indicates, if true, that the value in the credential field should not be saved by the credential helper because its usefulness is limited in time. For example, an HTTP Digest credential value is computed using a nonce and reusing it will not result in successful authentication. This may also be used for situations with short duration (e.g., 24-hour) credentials. The default value is false.
The credential helper will still be invoked with store or erase so that it can determine whether the operation was successful.
This value should not be sent unless the appropriate capability (see below) is provided on input.
This value provides an opaque state that will be passed back to this helper if it is called again. Each different credential helper may specify this once. The value should include a prefix unique to the credential helper and should ignore values that don't match its prefix.
This value should not be sent unless the appropriate capability (see below) is provided on input.
This is a boolean value, which, if enabled, indicates that this authentication is a non-final part of a multistage authentication step. This is common in protocols such as NTLM and Kerberos, where two rounds of client authentication are required, and setting this flag allows the credential helper to implement the multistage authentication step. This flag should only be sent if a further stage is required; that is, if another round of authentication is expected.
This value should not be sent unless the appropriate capability (see below) is provided on input. This attribute is one-way from a credential helper to pass information to Git (or other programs invoking git credential).
When an HTTP response is received by Git that includes one or more WWW-Authenticate authentication headers, these will be passed by Git to credential helpers.
Each WWW-Authenticate header value is passed as a multi-valued attribute wwwauth[], where the order of the attributes is the same as they appear in the HTTP response. This attribute is one-way from Git to pass additional information to credential helpers.
This signals that Git, or the helper, as appropriate, supports the capability in question. This can be used to provide better, more specific data as part of the protocol. A capability[] directive must precede any value depending on it and these directives should be the first item announced in the protocol.
There are two currently supported capabilities. The first is authtype, which indicates that the authtype, credential, and ephemeral values are understood. The second is state, which indicates that the state[] and continue values are understood.
It is not obligatory to use the additional features just because the capability is supported, but they should not be provided without the capability.
Unrecognised attributes and capabilities are silently discarded.
For git credential capability, the format is slightly different. First, a version 0 announcement is made to indicate the current version of the protocol, and then each capability is announced with a line like capability authtype. Credential helpers may also implement this format, again with the capability argument. Additional lines may be added in the future; callers should ignore lines which they don't understand.
Because this is a new part of the credential helper protocol, older versions of Git, as well as some credential helpers, may not support it. If a non-zero exit status is received, or if the first line doesn't start with the word version and a space, callers should assume that no capabilities are supported.
The intention of this format is to differentiate it from the credential output in an unambiguous way. It is possible to use very simple credential helpers (e.g., inline shell scripts) which always produce identical output. Using a distinct format allows users to continue to use this syntax without having to worry about correctly implementing capability advertisements or accidentally confusing callers querying for capabilities.
Part of the the section called “git(1)” suite
You probably don't want to invoke this command yourself; it is started automatically when you use the section called “git-credential-cache(1)”.
This command listens on the Unix domain socket specified by <socket-path> for git-credential-cache clients. Clients may store and retrieve credentials. Each credential is held for a timeout specified by the client; once no credentials are held, the daemon exits.
If the --debug option is specified, the daemon does not close its stderr stream, and may output extra diagnostics to it even after it has begun listening for clients.
Part of the the section called “git(1)” suite
This command caches credentials for use by future Git programs. The stored credentials are kept in memory of the cache-daemon process (instead of being written to a file) and are forgotten after a configurable timeout. Credentials are forgotten sooner if the cache-daemon dies, for example if the system restarts. The cache is accessible over a Unix domain socket, restricted to the current user by filesystem permissions.
You probably don't want to invoke this command directly; it is meant to be used as a credential helper by other parts of Git. See the section called “gitcredentials(7)” or EXAMPLES below.
If you would like the daemon to exit early, forgetting all cached credentials before their timeout, you can issue an exit action:
git credential-cache exit
The point of this helper is to reduce the number of times you must type your username or password. For example:
$ git config credential.helper cache $ git push http://example.com/repo.git Username: <type your username> Password: <type your password> [work for 5 more minutes] $ git push http://example.com/repo.git [your credentials are used automatically]
You can provide options via the credential.helper configuration variable (this example increases the cache time to 1 hour):
$ git config credential.helper 'cache --timeout=3600'
Some remotes accept personal access tokens, which are randomly generated and hard to memorise. They typically have a lifetime of weeks or months.
git-credential-cache is inherently unsuitable for persistent storage of personal access tokens. The credential will be forgotten after the cache timeout. Even if you configure a long timeout, credentials will be forgotten if the daemon dies.
To avoid frequently regenerating personal access tokens, configure a credential helper with persistent storage. Alternatively, configure an OAuth credential helper to generate credentials automatically. See the section called “gitcredentials(7)”, sections "Available helpers" and "OAuth".
Part of the the section called “git(1)” suite
Using this helper will store your passwords unencrypted on disk, protected only by filesystem permissions. If this is not an acceptable security tradeoff, try the section called “git-credential-cache(1)”, or find a helper that integrates with secure storage provided by your operating system.
This command stores credentials indefinitely on disk for use by future Git programs.
You probably don't want to invoke this command directly; it is meant to be used as a credential helper by other parts of git. See the section called “gitcredentials(7)” or EXAMPLES below.
If not set explicitly with --file, there are two files where git-credential-store will search for credentials in order of precedence:
For credential lookups, the files are read in the order given above, with the first matching credential found taking precedence over credentials found in files further down the list.
Credential storage will by default write to the first existing file in the list. If none of these files exist, ~/.git-credentials will be created and written to.
When erasing credentials, matching credentials will be erased from all files.
The point of this helper is to reduce the number of times you must type your username or password. For example:
$ git config credential.helper store $ git push http://example.com/repo.git Username: <type your username> Password: <type your password> [several days later] $ git push http://example.com/repo.git [your credentials are used automatically]
The .git-credentials file is stored in plaintext. Each credential is stored on its own line as a URL like:
https://user:pass@example.com
No other kinds of lines (e.g. empty lines or comment lines) are allowed in the file, even though some may be silently ignored. Do not view or edit the file with editors.
When Git needs authentication for a particular URL context, credential-store will consider that context a pattern to match against each entry in the credentials file. If the protocol, hostname, and username (if we already have one) match, then the password is returned to Git. See the discussion of configuration in the section called “gitcredentials(7)” for more information.
Part of the the section called “git(1)” suite
git cvsexportcommit [-h] [-u] [-v] [-c] [-P] [-p] [-a] [-d <cvsroot>]
[-w <cvs-workdir>] [-W] [-f] [-m <msgprefix>] [<parent-commit>] <commit-id>
Exports a commit from Git to a CVS checkout, making it easier to merge patches from a Git repository into a CVS repository.
Specify the name of a CVS checkout using the -w switch or execute it from the root of the CVS working copy. In the latter case GIT_DIR must be defined. See examples below.
It does its best to do the safe thing, it will check that the files are unchanged and up to date in the CVS checkout, and it will not autocommit by default.
Supports file additions, removals, and commits that affect binary files.
If the commit is a merge commit, you must tell git cvsexportcommit what parent the changeset should be done against.
$ export GIT_DIR=~/project/.git $ cd ~/project_cvs_checkout $ git cvsexportcommit -v <commit-sha1> $ cvs commit -F .msg <files>
$ git cvsexportcommit -v -c -w ~/project_cvs_checkout <commit-sha1>
$ export GIT_DIR=~/project/.git $ cd ~/project_cvs_checkout $ git cherry cvshead myhead | sed -n 's/^+ //p' | xargs -l1 git cvsexportcommit -c -p -v
Part of the the section called “git(1)” suite
git cvsimport [-o <branch-for-HEAD>] [-h] [-v] [-d <CVSROOT>]
[-A <author-conv-file>] [-p <options-for-cvsps>] [-P <file>]
[-C <git-repository>] [-z <fuzz>] [-i] [-k] [-u] [-s <subst>]
[-a] [-m] [-M <regex>] [-S <regex>] [-L <commit-limit>]
[-r <remote>] [-R] [<CVS-module>]
WARNING: git cvsimport uses cvsps version 2, which is considered deprecated; it does not work with cvsps version 3 and later. If you are performing a one-shot import of a CVS repository consider using cvs2git or cvs-fast-export.
Imports a CVS repository into Git. It will either create a new repository, or incrementally import into an existing one.
Splitting the CVS log into patch sets is done by cvsps. At least version 2.1 is required.
WARNING: for certain situations the import leads to incorrect results. Please see the section ISSUES for further reference.
You should never do any work of your own on the branches that are created by git cvsimport. By default initial import will create and populate a "master" branch from the CVS repository's main branch which you're free to work with; after that, you need to git merge incremental imports, or any CVS branches, yourself. It is advisable to specify a named remote via -r to separate and protect the incoming branches.
If you intend to set up a shared public repository that all developers can read/write, or if you want to use the section called “git-cvsserver(1)”, then you probably want to make a bare clone of the imported repository, and use the clone as the shared repository. See the section called “gitcvs-migration(7)”.
When no remote is specified (via -r) the HEAD branch from CVS is imported to the origin branch within the Git repository, as HEAD already has a special meaning for Git. When a remote is specified the HEAD branch is named remotes/<remote>/master mirroring git clone behaviour. Use this option if you want to import into a different branch.
Use -o master for continuing an import that was initially done by the old cvs2git tool.
Additional options for cvsps. The options -u and -A are implicit and should not be used here.
If you need to pass multiple options, separate them with a comma.
Attempt to detect merges based on the commit message with a custom regex. It can be used with -m to enable the default regexes as well. You must escape forward slashes.
The regex must capture the source branch name in $1.
This option can be used several times to provide several detection regexes.
CVS by default uses the Unix username when writing its commit logs. Using this option and an author-conv-file maps the name recorded in CVS to author name, e-mail and optional time zone:
exon=Andreas Ericsson <ae@op5.se>
spawn=Simon Pawn <spawn@frog-pond.org> America/Chicagogit cvsimport will make it appear as those authors had their GIT_AUTHOR_NAME and GIT_AUTHOR_EMAIL set properly all along. If a time zone is specified, GIT_AUTHOR_DATE will have the corresponding offset applied.
For convenience, this data is saved to $GIT_DIR/cvs-authors each time the -A option is provided and read from that same file each time git cvsimport is run.
It is not recommended to use this feature if you intend to export changes back to CVS again later with git cvsexportcommit.
Generate a $GIT_DIR/cvs-revisions file containing a mapping from CVS revision numbers to newly-created Git commit IDs. The generated file will contain one line for each (filename, revision) pair imported; each line will look like
src/widget.c 1.1 1d862f173cdc7325b6fa6d2ae1cfd61fd1b512b7
The revision data is appended to the file if it already exists, for use when doing incremental imports.
This option may be useful if you have CVS revision numbers stored in commit messages, bug-tracking systems, email archives, and the like.
If -v is specified, the script reports what it is doing.
Otherwise, success is indicated the Unix way, i.e. by simply exiting with a zero exit status.
Problems related to timestamps:
Problems related to branches:
Problems related to tags:
If you suspect that any of these issues may apply to the repository you want to import, consider using cvs2git:
Part of the the section called “git(1)” suite
SSH:
export CVS_SERVER="git cvsserver"
cvs -d :ext:user@server/path/repo.git co <HEAD_name>
pserver (/etc/inetd.conf):
cvspserver stream tcp nowait nobody /usr/bin/git-cvsserver git-cvsserver pserver
Usage:
git-cvsserver [<options>] [pserver|server] [<directory> …]
This application is a CVS emulation layer for Git.
It is highly functional. However, not all methods are implemented, and for those methods that are implemented, not all switches are implemented.
Testing has been done using both the CLI CVS client, and the Eclipse CVS plugin. Most functionality works fine with both of these clients.
All these options obviously only make sense if enforced by the server side. They have been implemented to resemble the the section called “git-daemon(1)” options as closely as possible.
CVS clients cannot tag, branch or perform Git merges.
git-cvsserver maps Git branches to CVS modules. This is very different from what most CVS users would expect since in CVS modules usually represent one or more directories.
If you are going to offer CVS access via pserver, add a line in /etc/inetd.conf like
cvspserver stream tcp nowait nobody git-cvsserver pserver
Note: Some inetd servers let you specify the name of the executable independently of the value of argv[0] (i.e. the name the program assumes it was executed with). In this case the correct line in /etc/inetd.conf looks like
cvspserver stream tcp nowait nobody /usr/bin/git-cvsserver git-cvsserver pserver
Only anonymous access is provided by pserver by default. To commit you will have to create pserver accounts, simply add a gitcvs.authdb setting in the config file of the repositories you want the cvsserver to allow writes to, for example:
[gitcvs]
authdb = /etc/cvsserver/passwdThe format of these files is username followed by the encrypted password, for example:
myuser:sqkNi8zPf01HI myuser:$1$9K7FzU28$VfF6EoPYCJEYcVQwATgOP/ myuser:$5$.NqmNH1vwfzGpV8B$znZIcumu1tNLATgV2l6e1/mY8RzhUDHMOaVOeL1cxV3
You can use the htpasswd facility that comes with Apache to make these files, but only with the -d option (or -B if your system supports it).
Preferably use the system specific utility that manages password hash creation in your platform (e.g. mkpasswd in Linux, encrypt in OpenBSD or pwhash in NetBSD) and paste it in the right location.
Then provide your password via the pserver method, for example:
cvs -d:pserver:someuser:somepassword@server:/path/repo.git co <HEAD_name>
No special setup is needed for SSH access, other than having Git tools in the PATH. If you have clients that do not accept the CVS_SERVER environment variable, you can rename git-cvsserver to cvs.
Note: Newer CVS versions (>= 1.12.11) also support specifying CVS_SERVER directly in CVSROOT like
cvs -d ":ext;CVS_SERVER=git cvsserver:user@server/path/repo.git" co <HEAD_name>
This has the advantage that it will be saved in your CVS/Root files and you don't need to worry about always setting the correct environment variable. SSH users restricted to git-shell don't need to override the default with CVS_SERVER (and shouldn't) as git-shell understands cvs to mean git-cvsserver and pretends that the other end runs the real cvs better.
For each repo that you want accessible from CVS you need to edit config in the repo and add the following section.
[gitcvs]
enabled=1
# optional for debugging
logFile=/path/to/logfileNote: you need to ensure each user that is going to invoke git-cvsserver has write access to the log file and to the database (see Database Backend. If you want to offer write access over SSH, the users of course also need write access to the Git repository itself.
You also need to ensure that each repository is "bare" (without a Git index file) for cvs commit to work. See the section called “gitcvs-migration(7)”.
All configuration variables can also be overridden for a specific method of access. Valid method names are "ext" (for SSH access) and "pserver". The following example configuration would disable pserver access while still allowing access over SSH.
[gitcvs]
enabled=0
[gitcvs "ext"]
enabled=1If you didn't specify the CVSROOT/CVS_SERVER directly in the checkout command, automatically saving it in your CVS/Root files, then you need to set them explicitly in your environment. CVSROOT should be set as per normal, but the directory should point at the appropriate Git repo. As above, for SSH clients not restricted to git-shell, CVS_SERVER should be set to git-cvsserver.
export CVSROOT=:ext:user@server:/var/git/project.git export CVS_SERVER="git cvsserver"
Clients should now be able to check out the project. Use the CVS module name to indicate what Git head you want to check out. This also sets the name of your newly checked-out directory, unless you tell it otherwise with -d <dir-name>. For example, this checks out master branch to the project-master directory:
cvs co -d project-master master
git-cvsserver uses one database per Git head (i.e. CVS module) to store information about the repository to maintain consistent CVS revision numbers. The database needs to be updated (i.e. written to) after every commit.
If the commit is done directly by using git (as opposed to using git-cvsserver) the update will need to happen on the next repository access by git-cvsserver, independent of access method and requested operation.
That means that even if you offer only read access (e.g. by using the pserver method), git-cvsserver should have write access to the database to work reliably (otherwise you need to make sure that the database is up to date any time git-cvsserver is executed).
By default it uses SQLite databases in the Git directory, named gitcvs.<module-name>.sqlite. Note that the SQLite backend creates temporary files in the same directory as the database file on write so it might not be enough to grant the users using git-cvsserver write access to the database file without granting them write access to the directory, too.
The database cannot be reliably regenerated in a consistent form after the branch it is tracking has changed. Example: For merged branches, git-cvsserver only tracks one branch of development, and after a git merge an incrementally updated database may track a different branch than a database regenerated from scratch, causing inconsistent CVS revision numbers. git-cvsserver has no way of knowing which branch it would have picked if it had been run incrementally pre-merge. So if you have to fully or partially (from old backup) regenerate the database, you should be suspicious of pre-existing CVS sandboxes.
You can configure the database backend with the following configuration variables:
git-cvsserver uses the Perl DBI module. Please also read its documentation if changing these variables, especially about DBI->connect().
All variables can also be set per access method, see above.
In dbDriver and dbUser you can use the following variables:
These variables obviate the need for command-line options in some circumstances, allowing easier restricted usage through git-shell.
When these environment variables are set, the corresponding command-line arguments may not be used.
To get a checkout with the Eclipse CVS client:
Protocol notes: If you are using anonymous access via pserver, just select that. Those using SSH access should choose the ext protocol, and configure ext access on the Preferences→Team→CVS→ExtConnection pane. Set CVS_SERVER to "git cvsserver". Note that password support is not good when using ext, you will definitely want to have SSH keys setup.
Alternatively, you can just use the non-standard extssh protocol that Eclipse offer. In that case CVS_SERVER is ignored, and you will have to replace the cvs utility on the server with git-cvsserver or manipulate your .bashrc so that calling cvs effectively calls git-cvsserver.
All the operations required for normal use are supported, including checkout, diff, status, update, log, add, remove, commit.
Most CVS command arguments that read CVS tags or revision numbers (typically -r) work, and also support any git refspec (tag, branch, commit ID, etc). However, CVS revision numbers for non-default branches are not well emulated, and cvs log does not show tags or branches at all. (Non-main-branch CVS revision numbers superficially resemble CVS revision numbers, but they actually encode a git commit ID directly, rather than represent the number of revisions since the branch point.)
Note that there are two ways to checkout a particular branch. As described elsewhere on this page, the "module" parameter of cvs checkout is interpreted as a branch name, and it becomes the main branch. It remains the main branch for a given sandbox even if you temporarily make another branch sticky with cvs update -r. Alternatively, the -r argument can indicate some other branch to actually checkout, even though the module is still the "main" branch. Tradeoffs (as currently implemented): Each new "module" creates a new database on disk with a history for the given module, and after the database is created, operations against that main branch are fast. Or alternatively, -r doesn't take any extra disk space, but may be significantly slower for many operations, like cvs update.
If you want to refer to a git refspec that has characters that are not allowed by CVS, you have two options. First, it may just work to supply the git refspec directly to the appropriate CVS -r argument; some CVS clients don't seem to do much sanity checking of the argument. Second, if that fails, you can use a special character escape mechanism that only uses characters that are valid in CVS tags. A sequence of 4 or 5 characters of the form (underscore ("_"), dash ("-"), one or two characters, and dash ("-")) can encode various characters based on the one or two letters: "s" for slash ("/"), "p" for period ("."), "u" for underscore ("_"), or two hexadecimal digits for any byte value at all (typically an ASCII number, or perhaps a part of a UTF-8 encoded character).
Legacy monitoring operations are not supported (edit, watch and related). Exports and tagging (tags and branches) are not supported at this stage.
By default the server leaves the -k mode blank for all files, which causes the CVS client to treat them as a text files, subject to end-of-line conversion on some platforms.
You can make the server use the end-of-line conversion attributes to set the -k modes for files by setting the gitcvs.usecrlfattr config variable. See the section called “gitattributes(5)” for more information about end-of-line conversion.
Alternatively, if gitcvs.usecrlfattr config is not enabled or the attributes do not allow automatic detection for a filename, then the server uses the gitcvs.allBinary config for the default setting. If gitcvs.allBinary is set, then file not otherwise specified will default to -kb mode. Otherwise the -k mode is left blank. But if gitcvs.allBinary is set to "guess", then the correct -k mode will be guessed based on the contents of the file.
For best consistency with cvs, it is probably best to override the defaults by setting gitcvs.usecrlfattr to true, and gitcvs.allBinary to "guess".
Part of the the section called “git(1)” suite
gitdaemon[--verbose] [--syslog] [--export-all]
[--timeout=<n>] [--init-timeout=<n>] [--max-connections=<n>]
[--strict-paths] [--base-path=<path>] [--base-path-relaxed]
[--user-path|--user-path=<path>]
[--interpolated-path=<pathtemplate>]
[--reuseaddr] [--detach] [--pid-file=<file>]
[--enable=<service>] [--disable=<service>]
[--allow-override=<service>] [--forbid-override=<service>]
[--access-hook=<path>] [--[no-]informative-errors]
[--inetd|
[--listen=<host-or-ipaddr>] [--port=<n>]
[--user=<user> [--group=<group>]]]
[--log-destination=(stderr|syslog|none)]
[<directory>…]
A really simple TCP Git daemon that normally listens on port "DEFAULT_GIT_PORT" aka 9418. It waits for a connection asking for a service, and will serve that service if it is enabled.
It verifies that the directory has the magic file "git-daemon-export-ok", and it will refuse to export any Git directory that hasn't explicitly been marked for export this way (unless the --export-all parameter is specified). If you pass some directory paths as git daemon arguments, the offers are limited to repositories within those directories.
By default, only upload-pack service is enabled, which serves git fetch-pack and git ls-remote clients, which are invoked from git fetch, git pull, and git clone.
This is ideally suited for read-only updates, i.e., pulling from Git repositories.
An upload-archive also exists to serve git archive.
Send log messages to the specified destination. Note that this option does not imply --verbose, thus by default only error conditions will be logged. The <destination> must be one of:
The default destination is syslog if --inetd or --detach is specified, otherwise stderr.
Change daemon's uid and gid before entering the service loop. When only --user is given without --group, the primary group ID for the user is used. The values of the option are given to getpwnam(3) and getgrnam(3) and numeric IDs are not supported.
Giving these options is an error when used with --inetd; use the facility of inet daemon to achieve the same before spawning git daemon if needed.
Like many programs that switch user id, the daemon does not reset environment variables such as HOME when it runs git programs, e.g. upload-pack and receive-pack. When using this option, you may also want to set and export HOME to point at the home directory of <user> before starting the daemon, and make sure any Git configuration files in that directory are readable by <user>.
Every time a client connects, first run an external command specified by the <path> with service name (e.g. "upload-pack"), path to the repository, hostname (%H), canonical hostname (%CH), IP address (%IP), and TCP port (%P) as its command-line arguments. The external command can decide to decline the service by exiting with a non-zero status (or to allow it by exiting with a zero status). It can also look at the $REMOTE_ADDR and $REMOTE_PORT environment variables to learn about the requestor when making this decision.
The external command can optionally write a single line to its standard output to be sent to the requestor as an error message when it declines the service.
These services can be globally enabled/disabled using the command-line options of this command. If finer-grained control is desired (e.g. to allow git archive to be run against only in a few selected repositories the daemon serves), the per-repository configuration file can be used to enable or disable them.
$ grep 9418 /etc/services git 9418/tcp # Git Version Control System
To set up git daemon as an inetd service that handles any repository within /pub/foo or /pub/bar, place an entry like the following into /etc/inetd all on one line:
git stream tcp nowait nobody /usr/bin/git
git daemon --inetd --verbose --export-all
/pub/foo /pub/barTo set up git daemon as an inetd service that handles repositories for different virtual hosts, www.example.com and www.example.org, place an entry like the following into /etc/inetd all on one line:
git stream tcp nowait nobody /usr/bin/git
git daemon --inetd --verbose --export-all
--interpolated-path=/pub/%H%D
/pub/www.example.org/software
/pub/www.example.com/software
/softwareIn this example, the root-level directory /pub will contain a subdirectory for each virtual host name supported. Further, both hosts advertise repositories simply as git://www.example.com/software/repo.git. For pre-1.4.0 clients, a symlink from /software into the appropriate default repository could be made as well.
To set up git daemon as a regular, non-inetd service that handles repositories for multiple virtual hosts based on their IP addresses, start the daemon like this:
git daemon --verbose --export-all
--interpolated-path=/pub/%IP/%D
/pub/192.168.1.200/software
/pub/10.10.220.23/softwareIn this example, the root-level directory /pub will contain a subdirectory for each virtual host IP address supported. Repositories can still be accessed by hostname though, assuming they correspond to these IP addresses.
To enable git archive --remote and disable git fetch against a repository, have the following in the configuration file in the repository (that is the file config next to HEAD, refs and objects).
[daemon]
uploadpack = false
uploadarch = truegit daemon will set REMOTE_ADDR to the IP address of the client that connected to it, if the IP address is available. REMOTE_ADDR will be available in the environment of hooks called when services are performed.
Part of the the section called “git(1)” suite
git describe [--all] [--tags] [--contains] [--abbrev=<n>] [<commit-ish>…]
git describe [--all] [--tags] [--contains] [--abbrev=<n>] --dirty[=<mark>]
git describe <blob>
The command finds the most recent tag that is reachable from a commit. If the tag points to the commit, then only the tag is shown. Otherwise, it suffixes the tag name with the number of additional commits on top of the tagged object and the abbreviated object name of the most recent commit. The result is a "human-readable" object name which can also be used to identify the commit to other git commands.
By default (without --all or --tags) git describe only shows annotated tags. For more information about creating annotated tags see the -a and -s options to the section called “git-tag(1)”.
If the given object refers to a blob, it will be described as <commit-ish>:<path>, such that the blob can be found at <path> in the <commit-ish>, which itself describes the first commit in which this blob occurs in a reverse revision walk from HEAD.
With something like git.git current tree, I get:
[torvalds@g5 git]$ git describe parent v1.0.4-14-g2414721
i.e. the current head of my "parent" branch is based on v1.0.4, but since it has a few commits on top of that, describe has added the number of additional commits ("14") and an abbreviated object name for the commit itself ("2414721") at the end.
The number of additional commits is the number of commits which would be displayed by "git log v1.0.4..parent". The hash suffix is "-g" + an unambiguous abbreviation for the tip commit of parent (which was 2414721b194453f058079d897d13c4e377f92dc6). The length of the abbreviation scales as the repository grows, using the approximate number of objects in the repository and a bit of math around the birthday paradox, and defaults to a minimum of 7. The "g" prefix stands for "git" and is used to allow describing the version of a software depending on the SCM the software is managed with. This is useful in an environment where people may use different SCMs.
Doing a git describe on a tag-name will just show the tag name:
[torvalds@g5 git]$ git describe v1.0.4 v1.0.4
With --all, the command can use branch heads as references, so the output shows the reference path as well:
[torvalds@g5 git]$ git describe --all --abbrev=4 v1.0.5^2 tags/v1.0.0-21-g975b
[torvalds@g5 git]$ git describe --all --abbrev=4 HEAD^ heads/lt/describe-7-g975b
With --abbrev set to 0, the command can be used to find the closest tagname without any suffix:
[torvalds@g5 git]$ git describe --abbrev=0 v1.0.5^2 tags/v1.0.0
Note that the suffix you get if you type these commands today may be longer than what Linus saw above when he ran these commands, as your Git repository may have new commits whose object names begin with 975b that did not exist back then, and "-g975b" suffix alone may not be sufficient to disambiguate these commits.
For each commit-ish supplied, git describe will first look for a tag which tags exactly that commit. Annotated tags will always be preferred over lightweight tags, and tags with newer dates will always be preferred over tags with older dates. If an exact match is found, its name will be output and searching will stop.
If an exact match was not found, git describe will walk back through the commit history to locate an ancestor commit which has been tagged. The ancestor's tag will be output along with an abbreviation of the input commit-ish's SHA-1. If --first-parent was specified then the walk will only consider the first parent of each commit.
If multiple tags were found during the walk then the tag which has the fewest commits different from the input commit-ish will be selected and output. Here fewest commits different is defined as the number of commits which would be shown by git log tag..input will be the smallest number of commits possible.
Tree objects as well as tag objects not pointing at commits, cannot be described. When describing blobs, the lightweight tags pointing at blobs are ignored, but the blob is still described as <commit-ish>:<path> despite the lightweight tag being favorable.
Part of the the section called “git(1)” suite
Collects detailed information about the user's machine, Git client, and repository state and packages that information into a zip archive. The generated archive can then, for example, be shared with the Git mailing list to help debug an issue or serve as a reference for independent debugging.
By default, the following information is captured in the archive:
Additional information can be collected by selecting a different diagnostic mode using the --mode option.
This tool differs from the section called “git-bugreport(1)” in that it collects much more detailed information with a greater focus on reporting the size and data shape of repository contents.
Specify the type of diagnostics that should be collected. The default behavior of git diagnose is equivalent to --mode=stats.
The --mode=all option collects everything included in --mode=stats, as well as copies of .git, .git/hooks, .git/info, .git/logs, and .git/objects/info directories. This additional information may be sensitive, as it can be used to reconstruct the full contents of the diagnosed repository. Users should exercise caution when sharing an archive generated with --mode=all.
Part of the the section called “git(1)” suite
Compares the files in the working tree and the index. When paths are specified, compares only those named paths. Otherwise all entries in the index are compared. The output format is the same as for git diff-index and git diff-tree.
Generate a diff using the "anchored diff" algorithm.
This option may be specified more than once.
If a line exists in both the source and destination, exists only once, and starts with <text>, this algorithm attempts to prevent it from appearing as a deletion or addition in the output. It uses the "patience diff" algorithm internally.
Choose a diff algorithm. The variants are as follows:
For instance, if you configured the diff.algorithm variable to a non-default value and want to use the default one, then you have to use --diff-algorithm=default option.
Generate a diffstat. By default, as much space as necessary will be used for the filename part, and the rest for the graph part. Maximum width defaults to terminal width, or 80 columns if not connected to a terminal, and can be overridden by <width>. The width of the filename part can be limited by giving another width <name-width> after a comma or by setting diff.statNameWidth=<name-width>. The width of the graph part can be limited by using --stat-graph-width=<graph-width> or by setting diff.statGraphWidth=<graph-width>. Using --stat or --stat-graph-width affects all commands generating a stat graph, while setting diff.statNameWidth or diff.statGraphWidth does not affect git format-patch. By giving a third parameter <count>, you can limit the output to the first <count> lines, followed by ... if there are more.
These parameters can also be set individually with --stat-width=<width>, --stat-name-width=<name-width> and --stat-count=<count>.
Output the distribution of relative amount of changes for each sub-directory. The behavior of --dirstat can be customized by passing it a comma separated list of parameters. The defaults are controlled by the diff.dirstat configuration variable (see the section called “git-config(1)”). The following parameters are available:
Example: The following will count changed files, while ignoring directories with less than 10% of the total amount of changed files, and accumulating child directory counts in the parent directories: --dirstat=files,10,cumulative.
When --raw, --numstat, --name-only or --name-status has been given, do not munge pathnames and use NULs as output field terminators.
Without this option, pathnames with "unusual" characters are quoted as explained for the configuration variable core.quotePath (see the section called “git-config(1)”).
Moved lines of code are colored differently. The <mode> defaults to no if the option is not given and to zebra if the option with no mode is given. The mode must be one of:
This configures how whitespace is ignored when performing the move detection for --color-moved. These modes can be given as a comma separated list:
By default, words are delimited by whitespace; see --word-diff-regex below. The <mode> defaults to plain, and must be one of:
[-removed-] and {added}. Makes no
attempts to escape the delimiters if they appear in the input,
so the output may be ambiguous.
Note that despite the name of the first mode, color is used to highlight the changed parts in all modes if enabled.
Use <regex> to decide what a word is, instead of considering runs of non-whitespace to be a word. Also implies --word-diff unless it was already enabled.
Every non-overlapping match of the <regex> is considered a word. Anything between these matches is considered whitespace and ignored(!) for the purposes of finding differences. You may want to append |[^[:space:]] to your regular expression to make sure that it matches all non-whitespace characters. A match that contains a newline is silently truncated(!) at the newline.
For example, --word-diff-regex=. will treat each character as a word and, correspondingly, show differences character by character.
The regex can also be set via a diff driver or configuration option, see the section called “gitattributes(5)” or the section called “git-config(1)”. Giving it explicitly overrides any diff driver or configuration setting. Diff drivers override configuration settings.
Break complete rewrite changes into pairs of delete and create. This serves two purposes:
It affects the way a change that amounts to a total rewrite of a file not as a series of deletion and insertion mixed together with a very few lines that happen to match textually as the context, but as a single deletion of everything old followed by a single insertion of everything new, and the number <m> controls this aspect of the -B option (defaults to 60%). -B/70% specifies that less than 30% of the original should remain in the result for Git to consider it a total rewrite (i.e. otherwise the resulting patch will be a series of deletion and insertion mixed together with context lines).
When used with -M, a totally-rewritten file is also considered as the source of a rename (usually -M only considers a file that disappeared as the source of a rename), and the number <n> controls this aspect of the -B option (defaults to 50%). -B20% specifies that a change with addition and deletion compared to 20% or more of the file's size are eligible for being picked up as a possible source of a rename to another file.
Omit the preimage for deletes, i.e. print only the header but not the diff between the preimage and /dev/null. The resulting patch is not meant to be applied with patch or git apply; this is solely for people who want to just concentrate on reviewing the text after the change. In addition, the output obviously lacks enough information to apply such a patch in reverse, even manually, hence the name of the option.
When used together with -B, omit also the preimage in the deletion part of a delete/create pair.
Select only files that are Added (A), Copied (C), Deleted (D), Modified (M), Renamed (R), have their type (i.e. regular file, symlink, submodule, …) changed (T), are Unmerged (U), are Unknown (X), or have had their pairing Broken (B). Any combination of the filter characters (including none) can be used. When * (All-or-none) is added to the combination, all paths are selected if there is any file that matches other criteria in the comparison; if there is no file that matches other criteria, nothing is selected.
Also, these upper-case letters can be downcased to exclude. E.g. --diff-filter=ad excludes added and deleted paths.
Note that not all diffs can feature all types. For instance, copied and renamed entries cannot appear if detection for those types is disabled.
Look for differences that change the number of occurrences of the specified <string> (i.e. addition/deletion) in a file. Intended for the scripter's use.
It is useful when you're looking for an exact block of code (like a struct), and want to know the history of that block since it first came into being: use the feature iteratively to feed the interesting block in the preimage back into -S, and keep going until you get the very first version of the block.
Binary files are searched as well.
Look for differences whose patch text contains added/removed lines that match <regex>.
To illustrate the difference between -S<regex> --pickaxe-regex and -G<regex>, consider a commit with the following diff in the same file:
+ return frotz(nitfol, two->ptr, 1, 0); ... - hit = frotz(nitfol, mf2.ptr, 1, 0);
While git log -G"frotz\(nitfol" will show this commit, git log -S"frotz\(nitfol" --pickaxe-regex will not (because the number of occurrences of that string did not change).
Unless --text is supplied patches of binary files without a textconv filter will be ignored.
See the pickaxe entry in the section called “gitdiffcore(7)” for more information.
Look for differences that change the number of occurrences of the specified object. Similar to -S, just the argument is different in that it doesn't search for a specific string but for a specific object id.
The object can be a blob or a submodule commit. It implies the -t option in git-log to also find trees.
Control the order in which files appear in the output. This overrides the diff.orderFile configuration variable (see the section called “git-config(1)”). To cancel diff.orderFile, use -O/dev/null.
The output order is determined by the order of glob patterns in <orderfile>. All files with pathnames that match the first pattern are output first, all files with pathnames that match the second pattern (but not the first) are output next, and so on. All files with pathnames that do not match any pattern are output last, as if there was an implicit match-all pattern at the end of the file. If multiple pathnames have the same rank (they match the same pattern but no earlier patterns), their output order relative to each other is the normal order.
<orderfile> is parsed as follows:
Patterns have the same syntax and semantics as patterns used for fnmatch(3) without the FNM_PATHNAME flag, except a pathname also matches a pattern if removing any number of the final pathname components matches the pattern. For example, the pattern "foo*bar" matches "fooasdfbar" and "foo/bar/baz/asdf" but not "foobarx".
diff.<driver>.trustExitCode or
environment variable GIT_EXTERNAL_DIFF_TRUST_EXIT_CODE is
false.
For more detailed explanation on these common options, see also the section called “gitdiffcore(7)”.
Diff against the "base" version, "our branch", or "their branch" respectively. With these options, diffs for merged entries are not shown.
The default is to diff against our branch (-2) and the cleanly resolved paths. The option -0 can be given to omit diff output for unmerged entries and just show "Unmerged".
The raw output format from git-diff-index, git-diff-tree, git-diff-files and git diff --raw are very similar.
These commands all compare two sets of things; what is compared differs:
The git-diff-tree command begins its output by printing the hash of what is being compared. After that, all the commands print one output line per changed file.
An output line is formatted this way:
in-place edit :100644 100644 bcd1234 0123456 M file0 copy-edit :100644 100644 abcd123 1234567 C68 file1 file2 rename-edit :100644 100644 abcd123 1234567 R86 file1 file3 create :000000 100644 0000000 1234567 A file4 delete :100644 000000 1234567 0000000 D file5 unmerged :000000 000000 0000000 0000000 U file6
That is, from the left to the right:
Possible status letters are:
Status letters C and R are always followed by a score (denoting the percentage of similarity between the source and target of the move or copy). Status letter M may be followed by a score (denoting the percentage of dissimilarity) for file rewrites.
The sha1 for "dst" is shown as all 0's if a file on the filesystem is out of sync with the index.
Example:
:100644 100644 5be4a4a 0000000 M file.c
Without the -z option, pathnames with "unusual" characters are quoted as explained for the configuration variable core.quotePath (see the section called “git-config(1)”). Using -z the filename is output verbatim and the line is terminated by a NUL byte.
git-diff-tree, git-diff-files and git-diff --raw can take -c or --cc option to generate diff output also for merge commits. The output differs from the format described above in the following way:
For -c and --cc, only the destination or final path is shown even if the file was renamed on any side of history. With --combined-all-paths, the name of the path in each parent is shown followed by the name of the path in the merge commit.
Examples for -c and --cc without --combined-all-paths:
::100644 100644 100644 fabadb8 cc95eb0 4866510 MM desc.c ::100755 100755 100755 52b7a2d 6d1ac04 d2ac7d7 RM bar.sh ::100644 100644 100644 e07d6c5 9042e82 ee91881 RR phooey.c
Examples when --combined-all-paths added to either -c or --cc:
::100644 100644 100644 fabadb8 cc95eb0 4866510 MM desc.c desc.c desc.c ::100755 100755 100755 52b7a2d 6d1ac04 d2ac7d7 RM foo.sh bar.sh bar.sh ::100644 100644 100644 e07d6c5 9042e82 ee91881 RR fooey.c fuey.c phooey.c
Note that combined diff lists only files which were modified from all parents.
Running the section called “git-diff(1)”, the section called “git-log(1)”, the section called “git-show(1)”, the section called “git-diff-index(1)”, the section called “git-diff-tree(1)”, or the section called “git-diff-files(1)” with the -p option produces patch text. You can customize the creation of patch text via the GIT_EXTERNAL_DIFF and the GIT_DIFF_OPTS environment variables (see the section called “git(1)”), and the diff attribute (see the section called “gitattributes(5)”).
What the -p option produces is slightly different from the traditional diff format:
It is preceded by a "git diff" header that looks like this:
diff --git a/file1 b/file2
The a/ and b/ filenames are the same unless rename/copy is involved. Especially, even for a creation or a deletion, /dev/null is not used in place of the a/ or b/ filenames.
When a rename/copy is involved, file1 and file2 show the name of the source file of the rename/copy and the name of the file that the rename/copy produces, respectively.
It is followed by one or more extended header lines:
oldmode<mode>
newmode<mode>
deletedfilemode<mode>
newfilemode<mode>
copyfrom<path>
copyto<path>
renamefrom<path>
renameto<path>
similarityindex<number>
dissimilarityindex<number>
index<hash>..<hash> <mode>
File modes <mode> are printed as 6-digit octal numbers including the file type and file permission bits.
Path names in extended headers do not include the a/ and b/ prefixes.
The similarity index is the percentage of unchanged lines, and the dissimilarity index is the percentage of changed lines. It is a rounded down integer, followed by a percent sign. The similarity index value of 100% is thus reserved for two equal files, while 100% dissimilarity means that no line from the old file made it into the new one.
The index line includes the blob object names before and after the change. The <mode> is included if the file mode does not change; otherwise, separate lines indicate the old and the new mode.
All the file1 files in the output refer to files before the commit, and all the file2 files refer to files after the commit. It is incorrect to apply each change to each file sequentially. For example, this patch will swap a and b:
diff --git a/a b/b rename from a rename to b diff --git a/b b/a rename from b rename to a
Any diff-generating command can take the -c or --cc option to produce a combined diff when showing a merge. This is the default format when showing merges with the section called “git-diff(1)” or the section called “git-show(1)”. Note also that you can give suitable --diff-merges option to any of these commands to force generation of diffs in a specific format.
A "combined diff" format looks like this:
diff --combined describe.c
index fabadb8,cc95eb0..4866510
--- a/describe.c
+++ b/describe.c
@@@ -98,20 -98,12 +98,20 @@@
return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1;
}
- static void describe(char *arg)
-static void describe(struct commit *cmit, int last_one)
++static void describe(char *arg, int last_one)
{
+ unsigned char sha1[20];
+ struct commit *cmit;
struct commit_list *list;
static int initialized = 0;
struct commit_name *n;
+ if (get_sha1(arg, sha1) < 0)
+ usage(describe_usage);
+ cmit = lookup_commit_reference(sha1);
+ if (!cmit)
+ usage(describe_usage);
+
if (!initialized) {
initialized = 1;
for_each_ref(get_name);It is preceded by a "git diff" header, that looks like this (when the -c option is used):
diff --combined file
or like this (when the --cc option is used):
diff --cc file
It is followed by one or more extended header lines (this example shows a merge with two parents):
index<hash>,<hash>..<hash>
mode<mode>,<mode>..<mode>
newfilemode<mode>
deletedfilemode<mode>,<mode>
The mode <mode>,<mode>..<mode> line appears only if at least one of the <mode> is different from the rest. Extended headers with information about detected content movement (renames and copying detection) are designed to work with the diff of two <tree-ish> and are not used by combined diff format.
It is followed by a two-line from-file/to-file header:
--- a/file +++ b/file
Similar to the two-line header for the traditional unified diff format, /dev/null is used to signal created or deleted files.
However, if the --combined-all-paths option is provided, instead of a two-line from-file/to-file, you get an N+1 line from-file/to-file header, where N is the number of parents in the merge commit:
--- a/file --- a/file --- a/file +++ b/file
This extended format can be useful if rename or copy detection is active, to allow you to see the original name of the file in different parents.
Chunk header format is modified to prevent people from accidentally feeding it to patch -p1. Combined diff format was created for review of merge commit changes, and was not meant to be applied. The change is similar to the change in the extended index header:
@@@ <from-file-range> <from-file-range> <to-file-range> @@@
There are (number of parents + 1) @ characters in the chunk header for combined diff format.
Unlike the traditional unified diff format, which shows two files A and B with a single column that has - (minus -- appears in A but removed in B), + (plus -- missing in A but added to B), or " " (space -- unchanged) prefix, this format compares two or more files file1, file2,… with one file X, and shows how X differs from each of fileN. One column for each of fileN is prepended to the output line to note how X's line is different from it.
A - character in the column N means that the line appears in fileN but it does not appear in the result. A + character in the column N means that the line appears in the result, and fileN does not have that line (in other words, the line was added, from the point of view of that parent).
In the above example output, the function signature was changed from both files (hence two - removals from both file1 and file2, plus ++ to mean one line that was added does not appear in either file1 or file2). Also, eight other lines are the same from file1 but do not appear in file2 (hence prefixed with +).
When shown by git diff-tree -c, it compares the parents of a merge commit with the merge result (i.e. file1..fileN are the parents). When shown by git diff-files -c, it compares the two unresolved merge parents with the working tree file (i.e. file1 is stage 2 aka "our version", file2 is stage 3 aka "their version").
The --summary option describes newly added, deleted, renamed and copied files. The --stat option adds diffstat(1) graph to the output. These options can be combined with other options, such as -p, and are meant for human consumption.
When showing a change that involves a rename or a copy, --stat output formats the pathnames compactly by combining common prefix and suffix of the pathnames. For example, a change that moves arch/i386/Makefile to arch/x86/Makefile while modifying 4 lines will be shown like this:
arch/{i386 => x86}/Makefile | 4 +--The --numstat option gives the diffstat(1) information but is designed for easier machine consumption. An entry in --numstat output looks like this:
1 2 README
3 1 arch/{i386 => x86}/MakefileThat is, from left to right:
When -z output option is in effect, the output is formatted this way:
1 2 README NUL 3 1 NUL arch/i386/Makefile NUL arch/x86/Makefile NUL
That is:
The extra NUL before the preimage path in renamed case is to allow scripts that read the output to tell if the current record being read is a single-path record or a rename/copy record without reading ahead. After reading added and deleted lines, reading up to NUL would yield the pathname, but if that is NUL, the record will show two paths.
Part of the the section called “git(1)” suite
Compare the content and mode of the blobs found in a tree object with the corresponding tracked files in the working tree, or with the corresponding paths in the index. When <path> arguments are present, compare only paths matching those patterns. Otherwise all tracked files are compared.
Generate a diff using the "anchored diff" algorithm.
This option may be specified more than once.
If a line exists in both the source and destination, exists only once, and starts with <text>, this algorithm attempts to prevent it from appearing as a deletion or addition in the output. It uses the "patience diff" algorithm internally.
Choose a diff algorithm. The variants are as follows:
For instance, if you configured the diff.algorithm variable to a non-default value and want to use the default one, then you have to use --diff-algorithm=default option.
Generate a diffstat. By default, as much space as necessary will be used for the filename part, and the rest for the graph part. Maximum width defaults to terminal width, or 80 columns if not connected to a terminal, and can be overridden by <width>. The width of the filename part can be limited by giving another width <name-width> after a comma or by setting diff.statNameWidth=<name-width>. The width of the graph part can be limited by using --stat-graph-width=<graph-width> or by setting diff.statGraphWidth=<graph-width>. Using --stat or --stat-graph-width affects all commands generating a stat graph, while setting diff.statNameWidth or diff.statGraphWidth does not affect git format-patch. By giving a third parameter <count>, you can limit the output to the first <count> lines, followed by ... if there are more.
These parameters can also be set individually with --stat-width=<width>, --stat-name-width=<name-width> and --stat-count=<count>.
Output the distribution of relative amount of changes for each sub-directory. The behavior of --dirstat can be customized by passing it a comma separated list of parameters. The defaults are controlled by the diff.dirstat configuration variable (see the section called “git-config(1)”). The following parameters are available:
Example: The following will count changed files, while ignoring directories with less than 10% of the total amount of changed files, and accumulating child directory counts in the parent directories: --dirstat=files,10,cumulative.
When --raw, --numstat, --name-only or --name-status has been given, do not munge pathnames and use NULs as output field terminators.
Without this option, pathnames with "unusual" characters are quoted as explained for the configuration variable core.quotePath (see the section called “git-config(1)”).
Moved lines of code are colored differently. The <mode> defaults to no if the option is not given and to zebra if the option with no mode is given. The mode must be one of:
This configures how whitespace is ignored when performing the move detection for --color-moved. These modes can be given as a comma separated list:
By default, words are delimited by whitespace; see --word-diff-regex below. The <mode> defaults to plain, and must be one of:
[-removed-] and {added}. Makes no
attempts to escape the delimiters if they appear in the input,
so the output may be ambiguous.
Note that despite the name of the first mode, color is used to highlight the changed parts in all modes if enabled.
Use <regex> to decide what a word is, instead of considering runs of non-whitespace to be a word. Also implies --word-diff unless it was already enabled.
Every non-overlapping match of the <regex> is considered a word. Anything between these matches is considered whitespace and ignored(!) for the purposes of finding differences. You may want to append |[^[:space:]] to your regular expression to make sure that it matches all non-whitespace characters. A match that contains a newline is silently truncated(!) at the newline.
For example, --word-diff-regex=. will treat each character as a word and, correspondingly, show differences character by character.
The regex can also be set via a diff driver or configuration option, see the section called “gitattributes(5)” or the section called “git-config(1)”. Giving it explicitly overrides any diff driver or configuration setting. Diff drivers override configuration settings.
Break complete rewrite changes into pairs of delete and create. This serves two purposes:
It affects the way a change that amounts to a total rewrite of a file not as a series of deletion and insertion mixed together with a very few lines that happen to match textually as the context, but as a single deletion of everything old followed by a single insertion of everything new, and the number <m> controls this aspect of the -B option (defaults to 60%). -B/70% specifies that less than 30% of the original should remain in the result for Git to consider it a total rewrite (i.e. otherwise the resulting patch will be a series of deletion and insertion mixed together with context lines).
When used with -M, a totally-rewritten file is also considered as the source of a rename (usually -M only considers a file that disappeared as the source of a rename), and the number <n> controls this aspect of the -B option (defaults to 50%). -B20% specifies that a change with addition and deletion compared to 20% or more of the file's size are eligible for being picked up as a possible source of a rename to another file.
Omit the preimage for deletes, i.e. print only the header but not the diff between the preimage and /dev/null. The resulting patch is not meant to be applied with patch or git apply; this is solely for people who want to just concentrate on reviewing the text after the change. In addition, the output obviously lacks enough information to apply such a patch in reverse, even manually, hence the name of the option.
When used together with -B, omit also the preimage in the deletion part of a delete/create pair.
Select only files that are Added (A), Copied (C), Deleted (D), Modified (M), Renamed (R), have their type (i.e. regular file, symlink, submodule, …) changed (T), are Unmerged (U), are Unknown (X), or have had their pairing Broken (B). Any combination of the filter characters (including none) can be used. When * (All-or-none) is added to the combination, all paths are selected if there is any file that matches other criteria in the comparison; if there is no file that matches other criteria, nothing is selected.
Also, these upper-case letters can be downcased to exclude. E.g. --diff-filter=ad excludes added and deleted paths.
Note that not all diffs can feature all types. For instance, copied and renamed entries cannot appear if detection for those types is disabled.
Look for differences that change the number of occurrences of the specified <string> (i.e. addition/deletion) in a file. Intended for the scripter's use.
It is useful when you're looking for an exact block of code (like a struct), and want to know the history of that block since it first came into being: use the feature iteratively to feed the interesting block in the preimage back into -S, and keep going until you get the very first version of the block.
Binary files are searched as well.
Look for differences whose patch text contains added/removed lines that match <regex>.
To illustrate the difference between -S<regex> --pickaxe-regex and -G<regex>, consider a commit with the following diff in the same file:
+ return frotz(nitfol, two->ptr, 1, 0); ... - hit = frotz(nitfol, mf2.ptr, 1, 0);
While git log -G"frotz\(nitfol" will show this commit, git log -S"frotz\(nitfol" --pickaxe-regex will not (because the number of occurrences of that string did not change).
Unless --text is supplied patches of binary files without a textconv filter will be ignored.
See the pickaxe entry in the section called “gitdiffcore(7)” for more information.
Look for differences that change the number of occurrences of the specified object. Similar to -S, just the argument is different in that it doesn't search for a specific string but for a specific object id.
The object can be a blob or a submodule commit. It implies the -t option in git-log to also find trees.
Control the order in which files appear in the output. This overrides the diff.orderFile configuration variable (see the section called “git-config(1)”). To cancel diff.orderFile, use -O/dev/null.
The output order is determined by the order of glob patterns in <orderfile>. All files with pathnames that match the first pattern are output first, all files with pathnames that match the second pattern (but not the first) are output next, and so on. All files with pathnames that do not match any pattern are output last, as if there was an implicit match-all pattern at the end of the file. If multiple pathnames have the same rank (they match the same pattern but no earlier patterns), their output order relative to each other is the normal order.
<orderfile> is parsed as follows:
Patterns have the same syntax and semantics as patterns used for fnmatch(3) without the FNM_PATHNAME flag, except a pathname also matches a pattern if removing any number of the final pathname components matches the pattern. For example, the pattern "foo*bar" matches "fooasdfbar" and "foo/bar/baz/asdf" but not "foobarx".
diff.<driver>.trustExitCode or
environment variable GIT_EXTERNAL_DIFF_TRUST_EXIT_CODE is
false.
For more detailed explanation on these common options, see also the section called “gitdiffcore(7)”.
The raw output format from git-diff-index, git-diff-tree, git-diff-files and git diff --raw are very similar.
These commands all compare two sets of things; what is compared differs:
The git-diff-tree command begins its output by printing the hash of what is being compared. After that, all the commands print one output line per changed file.
An output line is formatted this way:
in-place edit :100644 100644 bcd1234 0123456 M file0 copy-edit :100644 100644 abcd123 1234567 C68 file1 file2 rename-edit :100644 100644 abcd123 1234567 R86 file1 file3 create :000000 100644 0000000 1234567 A file4 delete :100644 000000 1234567 0000000 D file5 unmerged :000000 000000 0000000 0000000 U file6
That is, from the left to the right:
Possible status letters are:
Status letters C and R are always followed by a score (denoting the percentage of similarity between the source and target of the move or copy). Status letter M may be followed by a score (denoting the percentage of dissimilarity) for file rewrites.
The sha1 for "dst" is shown as all 0's if a file on the filesystem is out of sync with the index.
Example:
:100644 100644 5be4a4a 0000000 M file.c
Without the -z option, pathnames with "unusual" characters are quoted as explained for the configuration variable core.quotePath (see the section called “git-config(1)”). Using -z the filename is output verbatim and the line is terminated by a NUL byte.
git-diff-tree, git-diff-files and git-diff --raw can take -c or --cc option to generate diff output also for merge commits. The output differs from the format described above in the following way:
For -c and --cc, only the destination or final path is shown even if the file was renamed on any side of history. With --combined-all-paths, the name of the path in each parent is shown followed by the name of the path in the merge commit.
Examples for -c and --cc without --combined-all-paths:
::100644 100644 100644 fabadb8 cc95eb0 4866510 MM desc.c ::100755 100755 100755 52b7a2d 6d1ac04 d2ac7d7 RM bar.sh ::100644 100644 100644 e07d6c5 9042e82 ee91881 RR phooey.c
Examples when --combined-all-paths added to either -c or --cc:
::100644 100644 100644 fabadb8 cc95eb0 4866510 MM desc.c desc.c desc.c ::100755 100755 100755 52b7a2d 6d1ac04 d2ac7d7 RM foo.sh bar.sh bar.sh ::100644 100644 100644 e07d6c5 9042e82 ee91881 RR fooey.c fuey.c phooey.c
Note that combined diff lists only files which were modified from all parents.
Running the section called “git-diff(1)”, the section called “git-log(1)”, the section called “git-show(1)”, the section called “git-diff-index(1)”, the section called “git-diff-tree(1)”, or the section called “git-diff-files(1)” with the -p option produces patch text. You can customize the creation of patch text via the GIT_EXTERNAL_DIFF and the GIT_DIFF_OPTS environment variables (see the section called “git(1)”), and the diff attribute (see the section called “gitattributes(5)”).
What the -p option produces is slightly different from the traditional diff format:
It is preceded by a "git diff" header that looks like this:
diff --git a/file1 b/file2
The a/ and b/ filenames are the same unless rename/copy is involved. Especially, even for a creation or a deletion, /dev/null is not used in place of the a/ or b/ filenames.
When a rename/copy is involved, file1 and file2 show the name of the source file of the rename/copy and the name of the file that the rename/copy produces, respectively.
It is followed by one or more extended header lines:
oldmode<mode>
newmode<mode>
deletedfilemode<mode>
newfilemode<mode>
copyfrom<path>
copyto<path>
renamefrom<path>
renameto<path>
similarityindex<number>
dissimilarityindex<number>
index<hash>..<hash> <mode>
File modes <mode> are printed as 6-digit octal numbers including the file type and file permission bits.
Path names in extended headers do not include the a/ and b/ prefixes.
The similarity index is the percentage of unchanged lines, and the dissimilarity index is the percentage of changed lines. It is a rounded down integer, followed by a percent sign. The similarity index value of 100% is thus reserved for two equal files, while 100% dissimilarity means that no line from the old file made it into the new one.
The index line includes the blob object names before and after the change. The <mode> is included if the file mode does not change; otherwise, separate lines indicate the old and the new mode.
All the file1 files in the output refer to files before the commit, and all the file2 files refer to files after the commit. It is incorrect to apply each change to each file sequentially. For example, this patch will swap a and b:
diff --git a/a b/b rename from a rename to b diff --git a/b b/a rename from b rename to a
Any diff-generating command can take the -c or --cc option to produce a combined diff when showing a merge. This is the default format when showing merges with the section called “git-diff(1)” or the section called “git-show(1)”. Note also that you can give suitable --diff-merges option to any of these commands to force generation of diffs in a specific format.
A "combined diff" format looks like this:
diff --combined describe.c
index fabadb8,cc95eb0..4866510
--- a/describe.c
+++ b/describe.c
@@@ -98,20 -98,12 +98,20 @@@
return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1;
}
- static void describe(char *arg)
-static void describe(struct commit *cmit, int last_one)
++static void describe(char *arg, int last_one)
{
+ unsigned char sha1[20];
+ struct commit *cmit;
struct commit_list *list;
static int initialized = 0;
struct commit_name *n;
+ if (get_sha1(arg, sha1) < 0)
+ usage(describe_usage);
+ cmit = lookup_commit_reference(sha1);
+ if (!cmit)
+ usage(describe_usage);
+
if (!initialized) {
initialized = 1;
for_each_ref(get_name);It is preceded by a "git diff" header, that looks like this (when the -c option is used):
diff --combined file
or like this (when the --cc option is used):
diff --cc file
It is followed by one or more extended header lines (this example shows a merge with two parents):
index<hash>,<hash>..<hash>
mode<mode>,<mode>..<mode>
newfilemode<mode>
deletedfilemode<mode>,<mode>
The mode <mode>,<mode>..<mode> line appears only if at least one of the <mode> is different from the rest. Extended headers with information about detected content movement (renames and copying detection) are designed to work with the diff of two <tree-ish> and are not used by combined diff format.
It is followed by a two-line from-file/to-file header:
--- a/file +++ b/file
Similar to the two-line header for the traditional unified diff format, /dev/null is used to signal created or deleted files.
However, if the --combined-all-paths option is provided, instead of a two-line from-file/to-file, you get an N+1 line from-file/to-file header, where N is the number of parents in the merge commit:
--- a/file --- a/file --- a/file +++ b/file
This extended format can be useful if rename or copy detection is active, to allow you to see the original name of the file in different parents.
Chunk header format is modified to prevent people from accidentally feeding it to patch -p1. Combined diff format was created for review of merge commit changes, and was not meant to be applied. The change is similar to the change in the extended index header:
@@@ <from-file-range> <from-file-range> <to-file-range> @@@
There are (number of parents + 1) @ characters in the chunk header for combined diff format.
Unlike the traditional unified diff format, which shows two files A and B with a single column that has - (minus -- appears in A but removed in B), + (plus -- missing in A but added to B), or " " (space -- unchanged) prefix, this format compares two or more files file1, file2,… with one file X, and shows how X differs from each of fileN. One column for each of fileN is prepended to the output line to note how X's line is different from it.
A - character in the column N means that the line appears in fileN but it does not appear in the result. A + character in the column N means that the line appears in the result, and fileN does not have that line (in other words, the line was added, from the point of view of that parent).
In the above example output, the function signature was changed from both files (hence two - removals from both file1 and file2, plus ++ to mean one line that was added does not appear in either file1 or file2). Also, eight other lines are the same from file1 but do not appear in file2 (hence prefixed with +).
When shown by git diff-tree -c, it compares the parents of a merge commit with the merge result (i.e. file1..fileN are the parents). When shown by git diff-files -c, it compares the two unresolved merge parents with the working tree file (i.e. file1 is stage 2 aka "our version", file2 is stage 3 aka "their version").
The --summary option describes newly added, deleted, renamed and copied files. The --stat option adds diffstat(1) graph to the output. These options can be combined with other options, such as -p, and are meant for human consumption.
When showing a change that involves a rename or a copy, --stat output formats the pathnames compactly by combining common prefix and suffix of the pathnames. For example, a change that moves arch/i386/Makefile to arch/x86/Makefile while modifying 4 lines will be shown like this:
arch/{i386 => x86}/Makefile | 4 +--The --numstat option gives the diffstat(1) information but is designed for easier machine consumption. An entry in --numstat output looks like this:
1 2 README
3 1 arch/{i386 => x86}/MakefileThat is, from left to right:
When -z output option is in effect, the output is formatted this way:
1 2 README NUL 3 1 NUL arch/i386/Makefile NUL arch/x86/Makefile NUL
That is:
The extra NUL before the preimage path in renamed case is to allow scripts that read the output to tell if the current record being read is a single-path record or a rename/copy record without reading ahead. After reading added and deleted lines, reading up to NUL would yield the pathname, but if that is NUL, the record will show two paths.
You can choose whether you want to trust the index file entirely (using the --cached flag) or ask the diff logic to show any files that don't match the stat state as being "tentatively changed". Both of these operations are very useful indeed.
If --cached is specified, it allows you to ask:
show me the differences between HEAD and the current index contents (the ones I'd write using 'git write-tree')
For example, let's say that you have worked on your working directory, updated some files in the index and are ready to commit. You want to see exactly what you are going to commit, without having to write a new tree object and compare it that way, and to do that, you just do
git diff-index --cached HEAD
Example: let's say I had renamed commit.c to git-commit.c, and I had done an update-index to make that effective in the index file. git diff-files wouldn't show anything at all, since the index file matches my working directory. But doing a git diff-index does:
torvalds@ppc970:~/git> git diff-index --cached HEAD :100644 000000 4161aecc6700a2eb579e842af0b7f22b98443f74 0000000000000000000000000000000000000000 D commit.c :000000 100644 0000000000000000000000000000000000000000 4161aecc6700a2eb579e842af0b7f22b98443f74 A git-commit.c
You can see easily that the above is a rename.
In fact, git diff-index --cached should always be entirely equivalent to actually doing a git write-tree and comparing that. Except this one is much nicer for the case where you just want to check where you are.
So doing a git diff-index --cached is basically very useful when you are asking yourself "what have I already marked for being committed, and what's the difference to a previous tree".
The "non-cached" mode takes a different approach, and is potentially the more useful of the two in that what it does can't be emulated with a git write-tree + git diff-tree. Thus that's the default mode. The non-cached version asks the question:
show me the differences between HEAD and the currently checked out tree - index contents _and_ files that aren't up to date
which is obviously a very useful question too, since that tells you what you could commit. Again, the output matches the git diff-tree -r output to a tee, but with a twist.
The twist is that if some file doesn't match the index, we don't have a backing store thing for it, and we use the magic "all-zero" sha1 to show that. So let's say that you have edited kernel/sched.c, but have not actually done a git update-index on it yet - there is no "object" associated with the new state, and you get:
torvalds@ppc970:~/v2.6/linux> git diff-index --abbrev HEAD :100644 100644 7476bb5ba 000000000 M kernel/sched.c
i.e., it shows that the tree has changed, and that kernel/sched.c is not up to date and may contain new stuff. The all-zero sha1 means that to get the real diff, you need to look at the object in the working directory directly rather than do an object-to-object diff.
As with other commands of this type, git diff-index does not actually look at the contents of the file at all. So maybe kernel/sched.c hasn't actually changed, and it's just that you touched it. In either case, it's a note that you need to git update-index it to make the index be in sync.
You can have a mixture of files show up as "has been updated" and "is still dirty in the working directory" together. You can always tell which file is in which state, since the "has been updated" ones show a valid sha1, and the "not in sync with the index" ones will always have the special all-zero sha1.
Part of the the section called “git(1)” suite
Show changes for file pairs provided on stdin. Input for this command must be in the NUL-terminated raw output format as generated by commands such as git diff-tree -z -r --raw. By default, the outputted diffs are computed and shown in the patch format when stdin closes.
A single NUL byte may be written to stdin between raw input lines to compute file pair diffs up to that point instead of waiting for stdin to close. A NUL byte is also written to the output to delimit between these batches of diffs.
Usage of this command enables the traditional diff pipeline to be broken up into separate stages where diff-pairs acts as the output phase. Other commands, such as diff-tree, may serve as a frontend to compute the raw diff format used as input.
Instead of computing diffs via git diff-tree -p -M in one step, diff-tree can compute the file pairs and rename information without the blob diffs. This output can be fed to diff-pairs to generate the underlying blob diffs as done in the following example:
git diff-tree -z -r -M $a $b | git diff-pairs -z
Computing the tree diff upfront with rename information allows patch output from diff-pairs to be progressively computed over the course of potentially multiple invocations.
Pathspecs are not currently supported by diff-pairs. Pathspec limiting should be performed by the upstream command generating the raw diffs used as input.
Tree objects are not currently supported as input and are rejected.
Abbreviated object IDs in the diff-pairs input are not supported. Outputted object IDs can be abbreviated using the --abbrev option.
Generate a diff using the "anchored diff" algorithm.
This option may be specified more than once.
If a line exists in both the source and destination, exists only once, and starts with <text>, this algorithm attempts to prevent it from appearing as a deletion or addition in the output. It uses the "patience diff" algorithm internally.
Choose a diff algorithm. The variants are as follows:
For instance, if you configured the diff.algorithm variable to a non-default value and want to use the default one, then you have to use --diff-algorithm=default option.
Generate a diffstat. By default, as much space as necessary will be used for the filename part, and the rest for the graph part. Maximum width defaults to terminal width, or 80 columns if not connected to a terminal, and can be overridden by <width>. The width of the filename part can be limited by giving another width <name-width> after a comma or by setting diff.statNameWidth=<name-width>. The width of the graph part can be limited by using --stat-graph-width=<graph-width> or by setting diff.statGraphWidth=<graph-width>. Using --stat or --stat-graph-width affects all commands generating a stat graph, while setting diff.statNameWidth or diff.statGraphWidth does not affect git format-patch. By giving a third parameter <count>, you can limit the output to the first <count> lines, followed by ... if there are more.
These parameters can also be set individually with --stat-width=<width>, --stat-name-width=<name-width> and --stat-count=<count>.
Output the distribution of relative amount of changes for each sub-directory. The behavior of --dirstat can be customized by passing it a comma separated list of parameters. The defaults are controlled by the diff.dirstat configuration variable (see the section called “git-config(1)”). The following parameters are available:
Example: The following will count changed files, while ignoring directories with less than 10% of the total amount of changed files, and accumulating child directory counts in the parent directories: --dirstat=files,10,cumulative.
When --raw, --numstat, --name-only or --name-status has been given, do not munge pathnames and use NULs as output field terminators.
Without this option, pathnames with "unusual" characters are quoted as explained for the configuration variable core.quotePath (see the section called “git-config(1)”).
Moved lines of code are colored differently. The <mode> defaults to no if the option is not given and to zebra if the option with no mode is given. The mode must be one of:
This configures how whitespace is ignored when performing the move detection for --color-moved. These modes can be given as a comma separated list:
By default, words are delimited by whitespace; see --word-diff-regex below. The <mode> defaults to plain, and must be one of:
[-removed-] and {added}. Makes no
attempts to escape the delimiters if they appear in the input,
so the output may be ambiguous.
Note that despite the name of the first mode, color is used to highlight the changed parts in all modes if enabled.
Use <regex> to decide what a word is, instead of considering runs of non-whitespace to be a word. Also implies --word-diff unless it was already enabled.
Every non-overlapping match of the <regex> is considered a word. Anything between these matches is considered whitespace and ignored(!) for the purposes of finding differences. You may want to append |[^[:space:]] to your regular expression to make sure that it matches all non-whitespace characters. A match that contains a newline is silently truncated(!) at the newline.
For example, --word-diff-regex=. will treat each character as a word and, correspondingly, show differences character by character.
The regex can also be set via a diff driver or configuration option, see the section called “gitattributes(5)” or the section called “git-config(1)”. Giving it explicitly overrides any diff driver or configuration setting. Diff drivers override configuration settings.
Break complete rewrite changes into pairs of delete and create. This serves two purposes:
It affects the way a change that amounts to a total rewrite of a file not as a series of deletion and insertion mixed together with a very few lines that happen to match textually as the context, but as a single deletion of everything old followed by a single insertion of everything new, and the number <m> controls this aspect of the -B option (defaults to 60%). -B/70% specifies that less than 30% of the original should remain in the result for Git to consider it a total rewrite (i.e. otherwise the resulting patch will be a series of deletion and insertion mixed together with context lines).
When used with -M, a totally-rewritten file is also considered as the source of a rename (usually -M only considers a file that disappeared as the source of a rename), and the number <n> controls this aspect of the -B option (defaults to 50%). -B20% specifies that a change with addition and deletion compared to 20% or more of the file's size are eligible for being picked up as a possible source of a rename to another file.
Omit the preimage for deletes, i.e. print only the header but not the diff between the preimage and /dev/null. The resulting patch is not meant to be applied with patch or git apply; this is solely for people who want to just concentrate on reviewing the text after the change. In addition, the output obviously lacks enough information to apply such a patch in reverse, even manually, hence the name of the option.
When used together with -B, omit also the preimage in the deletion part of a delete/create pair.
Select only files that are Added (A), Copied (C), Deleted (D), Modified (M), Renamed (R), have their type (i.e. regular file, symlink, submodule, …) changed (T), are Unmerged (U), are Unknown (X), or have had their pairing Broken (B). Any combination of the filter characters (including none) can be used. When * (All-or-none) is added to the combination, all paths are selected if there is any file that matches other criteria in the comparison; if there is no file that matches other criteria, nothing is selected.
Also, these upper-case letters can be downcased to exclude. E.g. --diff-filter=ad excludes added and deleted paths.
Note that not all diffs can feature all types. For instance, copied and renamed entries cannot appear if detection for those types is disabled.
Look for differences that change the number of occurrences of the specified <string> (i.e. addition/deletion) in a file. Intended for the scripter's use.
It is useful when you're looking for an exact block of code (like a struct), and want to know the history of that block since it first came into being: use the feature iteratively to feed the interesting block in the preimage back into -S, and keep going until you get the very first version of the block.
Binary files are searched as well.
Look for differences whose patch text contains added/removed lines that match <regex>.
To illustrate the difference between -S<regex> --pickaxe-regex and -G<regex>, consider a commit with the following diff in the same file:
+ return frotz(nitfol, two->ptr, 1, 0); ... - hit = frotz(nitfol, mf2.ptr, 1, 0);
While git log -G"frotz\(nitfol" will show this commit, git log -S"frotz\(nitfol" --pickaxe-regex will not (because the number of occurrences of that string did not change).
Unless --text is supplied patches of binary files without a textconv filter will be ignored.
See the pickaxe entry in the section called “gitdiffcore(7)” for more information.
Look for differences that change the number of occurrences of the specified object. Similar to -S, just the argument is different in that it doesn't search for a specific string but for a specific object id.
The object can be a blob or a submodule commit. It implies the -t option in git-log to also find trees.
Control the order in which files appear in the output. This overrides the diff.orderFile configuration variable (see the section called “git-config(1)”). To cancel diff.orderFile, use -O/dev/null.
The output order is determined by the order of glob patterns in <orderfile>. All files with pathnames that match the first pattern are output first, all files with pathnames that match the second pattern (but not the first) are output next, and so on. All files with pathnames that do not match any pattern are output last, as if there was an implicit match-all pattern at the end of the file. If multiple pathnames have the same rank (they match the same pattern but no earlier patterns), their output order relative to each other is the normal order.
<orderfile> is parsed as follows:
Patterns have the same syntax and semantics as patterns used for fnmatch(3) without the FNM_PATHNAME flag, except a pathname also matches a pattern if removing any number of the final pathname components matches the pattern. For example, the pattern "foo*bar" matches "fooasdfbar" and "foo/bar/baz/asdf" but not "foobarx".
diff.<driver>.trustExitCode or
environment variable GIT_EXTERNAL_DIFF_TRUST_EXIT_CODE is
false.
For more detailed explanation on these common options, see also the section called “gitdiffcore(7)”.
Running the section called “git-diff(1)”, the section called “git-log(1)”, the section called “git-show(1)”, the section called “git-diff-index(1)”, the section called “git-diff-tree(1)”, or the section called “git-diff-files(1)” with the -p option produces patch text. You can customize the creation of patch text via the GIT_EXTERNAL_DIFF and the GIT_DIFF_OPTS environment variables (see the section called “git(1)”), and the diff attribute (see the section called “gitattributes(5)”).
What the -p option produces is slightly different from the traditional diff format:
It is preceded by a "git diff" header that looks like this:
diff --git a/file1 b/file2
The a/ and b/ filenames are the same unless rename/copy is involved. Especially, even for a creation or a deletion, /dev/null is not used in place of the a/ or b/ filenames.
When a rename/copy is involved, file1 and file2 show the name of the source file of the rename/copy and the name of the file that the rename/copy produces, respectively.
It is followed by one or more extended header lines:
oldmode<mode>
newmode<mode>
deletedfilemode<mode>
newfilemode<mode>
copyfrom<path>
copyto<path>
renamefrom<path>
renameto<path>
similarityindex<number>
dissimilarityindex<number>
index<hash>..<hash> <mode>
File modes <mode> are printed as 6-digit octal numbers including the file type and file permission bits.
Path names in extended headers do not include the a/ and b/ prefixes.
The similarity index is the percentage of unchanged lines, and the dissimilarity index is the percentage of changed lines. It is a rounded down integer, followed by a percent sign. The similarity index value of 100% is thus reserved for two equal files, while 100% dissimilarity means that no line from the old file made it into the new one.
The index line includes the blob object names before and after the change. The <mode> is included if the file mode does not change; otherwise, separate lines indicate the old and the new mode.
All the file1 files in the output refer to files before the commit, and all the file2 files refer to files after the commit. It is incorrect to apply each change to each file sequentially. For example, this patch will swap a and b:
diff --git a/a b/b rename from a rename to b diff --git a/b b/a rename from b rename to a
Any diff-generating command can take the -c or --cc option to produce a combined diff when showing a merge. This is the default format when showing merges with the section called “git-diff(1)” or the section called “git-show(1)”. Note also that you can give suitable --diff-merges option to any of these commands to force generation of diffs in a specific format.
A "combined diff" format looks like this:
diff --combined describe.c
index fabadb8,cc95eb0..4866510
--- a/describe.c
+++ b/describe.c
@@@ -98,20 -98,12 +98,20 @@@
return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1;
}
- static void describe(char *arg)
-static void describe(struct commit *cmit, int last_one)
++static void describe(char *arg, int last_one)
{
+ unsigned char sha1[20];
+ struct commit *cmit;
struct commit_list *list;
static int initialized = 0;
struct commit_name *n;
+ if (get_sha1(arg, sha1) < 0)
+ usage(describe_usage);
+ cmit = lookup_commit_reference(sha1);
+ if (!cmit)
+ usage(describe_usage);
+
if (!initialized) {
initialized = 1;
for_each_ref(get_name);It is preceded by a "git diff" header, that looks like this (when the -c option is used):
diff --combined file
or like this (when the --cc option is used):
diff --cc file
It is followed by one or more extended header lines (this example shows a merge with two parents):
index<hash>,<hash>..<hash>
mode<mode>,<mode>..<mode>
newfilemode<mode>
deletedfilemode<mode>,<mode>
The mode <mode>,<mode>..<mode> line appears only if at least one of the <mode> is different from the rest. Extended headers with information about detected content movement (renames and copying detection) are designed to work with the diff of two <tree-ish> and are not used by combined diff format.
It is followed by a two-line from-file/to-file header:
--- a/file +++ b/file
Similar to the two-line header for the traditional unified diff format, /dev/null is used to signal created or deleted files.
However, if the --combined-all-paths option is provided, instead of a two-line from-file/to-file, you get an N+1 line from-file/to-file header, where N is the number of parents in the merge commit:
--- a/file --- a/file --- a/file +++ b/file
This extended format can be useful if rename or copy detection is active, to allow you to see the original name of the file in different parents.
Chunk header format is modified to prevent people from accidentally feeding it to patch -p1. Combined diff format was created for review of merge commit changes, and was not meant to be applied. The change is similar to the change in the extended index header:
@@@ <from-file-range> <from-file-range> <to-file-range> @@@
There are (number of parents + 1) @ characters in the chunk header for combined diff format.
Unlike the traditional unified diff format, which shows two files A and B with a single column that has - (minus -- appears in A but removed in B), + (plus -- missing in A but added to B), or " " (space -- unchanged) prefix, this format compares two or more files file1, file2,… with one file X, and shows how X differs from each of fileN. One column for each of fileN is prepended to the output line to note how X's line is different from it.
A - character in the column N means that the line appears in fileN but it does not appear in the result. A + character in the column N means that the line appears in the result, and fileN does not have that line (in other words, the line was added, from the point of view of that parent).
In the above example output, the function signature was changed from both files (hence two - removals from both file1 and file2, plus ++ to mean one line that was added does not appear in either file1 or file2). Also, eight other lines are the same from file1 but do not appear in file2 (hence prefixed with +).
When shown by git diff-tree -c, it compares the parents of a merge commit with the merge result (i.e. file1..fileN are the parents). When shown by git diff-files -c, it compares the two unresolved merge parents with the working tree file (i.e. file1 is stage 2 aka "our version", file2 is stage 3 aka "their version").
Part of the the section called “git(1)” suite
git diff-tree [--stdin] [-m] [-s] [-v] [--no-commit-id] [--pretty]
[-t] [-r] [-c | --cc] [--combined-all-paths] [--root] [--merge-base]
[<common-diff-options>] <tree-ish> [<tree-ish>] [<path>…]
Compare the content and mode of blobs found via two tree objects.
If there is only one <tree-ish> given, the commit is compared with its parents (see --stdin below).
Note that git diff-tree can use the tree encapsulated in a commit object.
Generate a diff using the "anchored diff" algorithm.
This option may be specified more than once.
If a line exists in both the source and destination, exists only once, and starts with <text>, this algorithm attempts to prevent it from appearing as a deletion or addition in the output. It uses the "patience diff" algorithm internally.
Choose a diff algorithm. The variants are as follows:
For instance, if you configured the diff.algorithm variable to a non-default value and want to use the default one, then you have to use --diff-algorithm=default option.
Generate a diffstat. By default, as much space as necessary will be used for the filename part, and the rest for the graph part. Maximum width defaults to terminal width, or 80 columns if not connected to a terminal, and can be overridden by <width>. The width of the filename part can be limited by giving another width <name-width> after a comma or by setting diff.statNameWidth=<name-width>. The width of the graph part can be limited by using --stat-graph-width=<graph-width> or by setting diff.statGraphWidth=<graph-width>. Using --stat or --stat-graph-width affects all commands generating a stat graph, while setting diff.statNameWidth or diff.statGraphWidth does not affect git format-patch. By giving a third parameter <count>, you can limit the output to the first <count> lines, followed by ... if there are more.
These parameters can also be set individually with --stat-width=<width>, --stat-name-width=<name-width> and --stat-count=<count>.
Output the distribution of relative amount of changes for each sub-directory. The behavior of --dirstat can be customized by passing it a comma separated list of parameters. The defaults are controlled by the diff.dirstat configuration variable (see the section called “git-config(1)”). The following parameters are available:
Example: The following will count changed files, while ignoring directories with less than 10% of the total amount of changed files, and accumulating child directory counts in the parent directories: --dirstat=files,10,cumulative.
When --raw, --numstat, --name-only or --name-status has been given, do not munge pathnames and use NULs as output field terminators.
Without this option, pathnames with "unusual" characters are quoted as explained for the configuration variable core.quotePath (see the section called “git-config(1)”).
Moved lines of code are colored differently. The <mode> defaults to no if the option is not given and to zebra if the option with no mode is given. The mode must be one of:
This configures how whitespace is ignored when performing the move detection for --color-moved. These modes can be given as a comma separated list:
By default, words are delimited by whitespace; see --word-diff-regex below. The <mode> defaults to plain, and must be one of:
[-removed-] and {added}. Makes no
attempts to escape the delimiters if they appear in the input,
so the output may be ambiguous.
Note that despite the name of the first mode, color is used to highlight the changed parts in all modes if enabled.
Use <regex> to decide what a word is, instead of considering runs of non-whitespace to be a word. Also implies --word-diff unless it was already enabled.
Every non-overlapping match of the <regex> is considered a word. Anything between these matches is considered whitespace and ignored(!) for the purposes of finding differences. You may want to append |[^[:space:]] to your regular expression to make sure that it matches all non-whitespace characters. A match that contains a newline is silently truncated(!) at the newline.
For example, --word-diff-regex=. will treat each character as a word and, correspondingly, show differences character by character.
The regex can also be set via a diff driver or configuration option, see the section called “gitattributes(5)” or the section called “git-config(1)”. Giving it explicitly overrides any diff driver or configuration setting. Diff drivers override configuration settings.
Break complete rewrite changes into pairs of delete and create. This serves two purposes:
It affects the way a change that amounts to a total rewrite of a file not as a series of deletion and insertion mixed together with a very few lines that happen to match textually as the context, but as a single deletion of everything old followed by a single insertion of everything new, and the number <m> controls this aspect of the -B option (defaults to 60%). -B/70% specifies that less than 30% of the original should remain in the result for Git to consider it a total rewrite (i.e. otherwise the resulting patch will be a series of deletion and insertion mixed together with context lines).
When used with -M, a totally-rewritten file is also considered as the source of a rename (usually -M only considers a file that disappeared as the source of a rename), and the number <n> controls this aspect of the -B option (defaults to 50%). -B20% specifies that a change with addition and deletion compared to 20% or more of the file's size are eligible for being picked up as a possible source of a rename to another file.
Omit the preimage for deletes, i.e. print only the header but not the diff between the preimage and /dev/null. The resulting patch is not meant to be applied with patch or git apply; this is solely for people who want to just concentrate on reviewing the text after the change. In addition, the output obviously lacks enough information to apply such a patch in reverse, even manually, hence the name of the option.
When used together with -B, omit also the preimage in the deletion part of a delete/create pair.
Select only files that are Added (A), Copied (C), Deleted (D), Modified (M), Renamed (R), have their type (i.e. regular file, symlink, submodule, …) changed (T), are Unmerged (U), are Unknown (X), or have had their pairing Broken (B). Any combination of the filter characters (including none) can be used. When * (All-or-none) is added to the combination, all paths are selected if there is any file that matches other criteria in the comparison; if there is no file that matches other criteria, nothing is selected.
Also, these upper-case letters can be downcased to exclude. E.g. --diff-filter=ad excludes added and deleted paths.
Note that not all diffs can feature all types. For instance, copied and renamed entries cannot appear if detection for those types is disabled.
Look for differences that change the number of occurrences of the specified <string> (i.e. addition/deletion) in a file. Intended for the scripter's use.
It is useful when you're looking for an exact block of code (like a struct), and want to know the history of that block since it first came into being: use the feature iteratively to feed the interesting block in the preimage back into -S, and keep going until you get the very first version of the block.
Binary files are searched as well.
Look for differences whose patch text contains added/removed lines that match <regex>.
To illustrate the difference between -S<regex> --pickaxe-regex and -G<regex>, consider a commit with the following diff in the same file:
+ return frotz(nitfol, two->ptr, 1, 0); ... - hit = frotz(nitfol, mf2.ptr, 1, 0);
While git log -G"frotz\(nitfol" will show this commit, git log -S"frotz\(nitfol" --pickaxe-regex will not (because the number of occurrences of that string did not change).
Unless --text is supplied patches of binary files without a textconv filter will be ignored.
See the pickaxe entry in the section called “gitdiffcore(7)” for more information.
Look for differences that change the number of occurrences of the specified object. Similar to -S, just the argument is different in that it doesn't search for a specific string but for a specific object id.
The object can be a blob or a submodule commit. It implies the -t option in git-log to also find trees.
Control the order in which files appear in the output. This overrides the diff.orderFile configuration variable (see the section called “git-config(1)”). To cancel diff.orderFile, use -O/dev/null.
The output order is determined by the order of glob patterns in <orderfile>. All files with pathnames that match the first pattern are output first, all files with pathnames that match the second pattern (but not the first) are output next, and so on. All files with pathnames that do not match any pattern are output last, as if there was an implicit match-all pattern at the end of the file. If multiple pathnames have the same rank (they match the same pattern but no earlier patterns), their output order relative to each other is the normal order.
<orderfile> is parsed as follows:
Patterns have the same syntax and semantics as patterns used for fnmatch(3) without the FNM_PATHNAME flag, except a pathname also matches a pattern if removing any number of the final pathname components matches the pattern. For example, the pattern "foo*bar" matches "fooasdfbar" and "foo/bar/baz/asdf" but not "foobarx".
diff.<driver>.trustExitCode or
environment variable GIT_EXTERNAL_DIFF_TRUST_EXIT_CODE is
false.
For more detailed explanation on these common options, see also the section called “gitdiffcore(7)”.
When --stdin is specified, the command does not take <tree-ish> arguments from the command line. Instead, it reads lines containing either two <tree>, one <commit>, or a list of <commit> from its standard input. (Use a single space as separator.)
When two trees are given, it compares the first tree with the second. When a single commit is given, it compares the commit with its parents. The remaining commits, when given, are used as if they are parents of the first commit.
When comparing two trees, the ID of both trees (separated by a space and terminated by a newline) is printed before the difference. When comparing commits, the ID of the first (or only) commit, followed by a newline, is printed.
The following flags further affect the behavior when comparing commits (but not trees).
Pretty-print the contents of the commit logs in a given format, where <format> can be one of oneline, short, medium, full, fuller, reference, email, raw, format:<string> and tformat:<string>. When <format> is none of the above, and has %placeholder in it, it acts as if --pretty=tformat:<format> were given.
See the "PRETTY FORMATS" section for some additional details for each format. When =<format> part is omitted, it defaults to medium.
Note: you can specify the default pretty format in the repository configuration (see the section called “git-config(1)”).
Instead of showing the full 40-byte hexadecimal commit object name, show a prefix that names the object uniquely. "--abbrev=<n>" (which also modifies diff output, if it is displayed) option can be used to specify the minimum length of the prefix.
This should make "--pretty=oneline" a whole lot more readable for people using 80-column terminals.
Perform a tab expansion (replace each tab with enough spaces to fill to the next display column that is a multiple of <n>) in the log message before showing it in the output. --expand-tabs is a short-hand for --expand-tabs=8, and --no-expand-tabs is a short-hand for --expand-tabs=0, which disables tab expansion.
By default, tabs are expanded in pretty formats that indent the log message by 4 spaces (i.e. medium, which is the default, full, and fuller).
Show the notes (see the section called “git-notes(1)”) that annotate the commit, when showing the commit log message. This is the default for git log, git show and git whatchanged commands when there is no --pretty, --format, or --oneline option given on the command line.
By default, the notes shown are from the notes refs listed in the core.notesRef and notes.displayRef variables (or corresponding environment overrides). See the section called “git-config(1)” for more details.
With an optional <ref> argument, use the ref to find the notes to display. The ref can specify the full refname when it begins with refs/notes/; when it begins with notes/, refs/ and otherwise refs/notes/ is prefixed to form the full name of the ref.
Multiple --notes options can be combined to control which notes are being displayed. Examples: "--notes=foo" will show only notes from "refs/notes/foo"; "--notes=foo --notes" will show both notes from "refs/notes/foo" and from the default notes ref(s).
If the commit is a merge, and if the pretty-format is not oneline, email or raw, an additional line is inserted before the Author: line. This line begins with "Merge: " and the hashes of ancestral commits are printed, separated by spaces. Note that the listed commits may not necessarily be the list of the direct parent commits if you have limited your view of history: for example, if you are only interested in changes related to a certain directory or file.
There are several built-in formats, and you can define additional formats by setting a pretty.<name> config option to either another format name, or a format: string, as described below (see the section called “git-config(1)”). Here are the details of the built-in formats:
oneline
<hash> <title-line>
This is designed to be as compact as possible.
short
commit <hash> Author: <author>
<title-line>
medium
commit <hash> Author: <author> Date: <author-date>
<title-line>
<full-commit-message>
full
commit <hash> Author: <author> Commit: <committer>
<title-line>
<full-commit-message>
fuller
commit <hash> Author: <author> AuthorDate: <author-date> Commit: <committer> CommitDate: <committer-date>
<title-line>
<full-commit-message>
reference
<abbrev-hash> (<title-line>, <short-author-date>)
This format is used to refer to another commit in a commit message and is the same as --pretty='format:%C(auto)%h (%s, %ad)'. By default, the date is formatted with --date=short unless another --date option is explicitly specified. As with any format: with format placeholders, its output is not affected by other options like --decorate and --walk-reflogs.
From <hash> <date> From: <author> Date: <author-date> Subject: [PATCH] <title-line>
<full-commit-message>
mboxrd
Like email, but lines in the commit message starting with "From " (preceded by zero or more ">") are quoted with ">" so they aren't confused as starting a new commit.
raw
The raw format shows the entire commit exactly as stored in the commit object. Notably, the hashes are displayed in full, regardless of whether --abbrev or --no-abbrev are used, and parents information show the true parent commits, without taking grafts or history simplification into account. Note that this format affects the way commits are displayed, but not the way the diff is shown e.g. with git log --raw. To get full object names in a raw diff format, use --no-abbrev.
format:<format-string>
The format:<format-string> format allows you to specify which information you want to show. It works a little bit like printf format, with the notable exception that you get a newline with %n instead of \n.
E.g, format:"The author of %h was %an, %ar%nThe title was >>%s<<%n" would show something like this:
The author of fe6e0ee was Junio C Hamano, 23 hours ago The title was >>t4119: test autocomputing -p<n> for traditional diff input.<<
The placeholders are:
Placeholders that expand to a single literal character:
Placeholders that affect formatting of later placeholders:
Placeholders that expand to information extracted from the commit:
ref names with custom decorations. The decorate string may be followed by a colon and zero or more comma-separated options. Option values may contain literal formatting codes. These must be used for commas (%x2C) and closing parentheses (%x29), due to their role in the option syntax.
For example, to produce decorations with no wrapping or tag annotations, and spaces as separators:
%(decorate:prefix=,suffix=,tag=,separator= )
human-readable name, like the section called “git-describe(1)”; empty string for undescribable commits. The describe string may be followed by a colon and zero or more comma-separated options. Descriptions can be inconsistent when tags are added or removed at the same time.
display the trailers of the body as interpreted by the section called “git-interpret-trailers(1)”. The trailers string may be followed by a colon and zero or more comma-separated options. If any option is provided multiple times, the last occurrence wins.
Some placeholders may depend on other options given to the revision traversal engine. For example, the %g* reflog options will insert an empty string unless we are traversing reflog entries (e.g., by git log -g). The %d and %D placeholders will use the "short" decoration format if --decorate was not already provided on the command line.
The boolean options accept an optional value [=<bool-value>]. The values taken by --type=bool git-config[1], like yes and off, are all accepted. Giving a boolean option without =<value> is equivalent to giving it with =true.
If you add a + (plus sign) after % of a placeholder, a line-feed is inserted immediately before the expansion if and only if the placeholder expands to a non-empty string.
If you add a - (minus sign) after % of a placeholder, all consecutive line-feeds immediately preceding the expansion are deleted if and only if the placeholder expands to an empty string.
If you add a ` ` (space) after % of a placeholder, a space is inserted immediately before the expansion if and only if the placeholder expands to a non-empty string.
tformat:
The tformat: format works exactly like format:, except that it provides "terminator" semantics instead of "separator" semantics. In other words, each commit has the message terminator character (usually a newline) appended, rather than a separator placed between entries. This means that the final entry of a single-line format will be properly terminated with a new line, just as the "oneline" format does. For example:
$ git log -2 --pretty=format:%h 4da45bef \ | perl -pe '$_ .= " -- NO NEWLINE\n" unless /\n/' 4da45be 7134973 -- NO NEWLINE $ git log -2 --pretty=tformat:%h 4da45bef \ | perl -pe '$_ .= " -- NO NEWLINE\n" unless /\n/' 4da45be 7134973
In addition, any unrecognized string that has a % in it is interpreted as if it has tformat: in front of it. For example, these two are equivalent:
$ git log -2 --pretty=tformat:%h 4da45bef $ git log -2 --pretty=%h 4da45bef
The raw output format from git-diff-index, git-diff-tree, git-diff-files and git diff --raw are very similar.
These commands all compare two sets of things; what is compared differs:
The git-diff-tree command begins its output by printing the hash of what is being compared. After that, all the commands print one output line per changed file.
An output line is formatted this way:
in-place edit :100644 100644 bcd1234 0123456 M file0 copy-edit :100644 100644 abcd123 1234567 C68 file1 file2 rename-edit :100644 100644 abcd123 1234567 R86 file1 file3 create :000000 100644 0000000 1234567 A file4 delete :100644 000000 1234567 0000000 D file5 unmerged :000000 000000 0000000 0000000 U file6
That is, from the left to the right:
Possible status letters are:
Status letters C and R are always followed by a score (denoting the percentage of similarity between the source and target of the move or copy). Status letter M may be followed by a score (denoting the percentage of dissimilarity) for file rewrites.
The sha1 for "dst" is shown as all 0's if a file on the filesystem is out of sync with the index.
Example:
:100644 100644 5be4a4a 0000000 M file.c
Without the -z option, pathnames with "unusual" characters are quoted as explained for the configuration variable core.quotePath (see the section called “git-config(1)”). Using -z the filename is output verbatim and the line is terminated by a NUL byte.
git-diff-tree, git-diff-files and git-diff --raw can take -c or --cc option to generate diff output also for merge commits. The output differs from the format described above in the following way:
For -c and --cc, only the destination or final path is shown even if the file was renamed on any side of history. With --combined-all-paths, the name of the path in each parent is shown followed by the name of the path in the merge commit.
Examples for -c and --cc without --combined-all-paths:
::100644 100644 100644 fabadb8 cc95eb0 4866510 MM desc.c ::100755 100755 100755 52b7a2d 6d1ac04 d2ac7d7 RM bar.sh ::100644 100644 100644 e07d6c5 9042e82 ee91881 RR phooey.c
Examples when --combined-all-paths added to either -c or --cc:
::100644 100644 100644 fabadb8 cc95eb0 4866510 MM desc.c desc.c desc.c ::100755 100755 100755 52b7a2d 6d1ac04 d2ac7d7 RM foo.sh bar.sh bar.sh ::100644 100644 100644 e07d6c5 9042e82 ee91881 RR fooey.c fuey.c phooey.c
Note that combined diff lists only files which were modified from all parents.
Running the section called “git-diff(1)”, the section called “git-log(1)”, the section called “git-show(1)”, the section called “git-diff-index(1)”, the section called “git-diff-tree(1)”, or the section called “git-diff-files(1)” with the -p option produces patch text. You can customize the creation of patch text via the GIT_EXTERNAL_DIFF and the GIT_DIFF_OPTS environment variables (see the section called “git(1)”), and the diff attribute (see the section called “gitattributes(5)”).
What the -p option produces is slightly different from the traditional diff format:
It is preceded by a "git diff" header that looks like this:
diff --git a/file1 b/file2
The a/ and b/ filenames are the same unless rename/copy is involved. Especially, even for a creation or a deletion, /dev/null is not used in place of the a/ or b/ filenames.
When a rename/copy is involved, file1 and file2 show the name of the source file of the rename/copy and the name of the file that the rename/copy produces, respectively.
It is followed by one or more extended header lines:
oldmode<mode>
newmode<mode>
deletedfilemode<mode>
newfilemode<mode>
copyfrom<path>
copyto<path>
renamefrom<path>
renameto<path>
similarityindex<number>
dissimilarityindex<number>
index<hash>..<hash> <mode>
File modes <mode> are printed as 6-digit octal numbers including the file type and file permission bits.
Path names in extended headers do not include the a/ and b/ prefixes.
The similarity index is the percentage of unchanged lines, and the dissimilarity index is the percentage of changed lines. It is a rounded down integer, followed by a percent sign. The similarity index value of 100% is thus reserved for two equal files, while 100% dissimilarity means that no line from the old file made it into the new one.
The index line includes the blob object names before and after the change. The <mode> is included if the file mode does not change; otherwise, separate lines indicate the old and the new mode.
All the file1 files in the output refer to files before the commit, and all the file2 files refer to files after the commit. It is incorrect to apply each change to each file sequentially. For example, this patch will swap a and b:
diff --git a/a b/b rename from a rename to b diff --git a/b b/a rename from b rename to a
Any diff-generating command can take the -c or --cc option to produce a combined diff when showing a merge. This is the default format when showing merges with the section called “git-diff(1)” or the section called “git-show(1)”. Note also that you can give suitable --diff-merges option to any of these commands to force generation of diffs in a specific format.
A "combined diff" format looks like this:
diff --combined describe.c
index fabadb8,cc95eb0..4866510
--- a/describe.c
+++ b/describe.c
@@@ -98,20 -98,12 +98,20 @@@
return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1;
}
- static void describe(char *arg)
-static void describe(struct commit *cmit, int last_one)
++static void describe(char *arg, int last_one)
{
+ unsigned char sha1[20];
+ struct commit *cmit;
struct commit_list *list;
static int initialized = 0;
struct commit_name *n;
+ if (get_sha1(arg, sha1) < 0)
+ usage(describe_usage);
+ cmit = lookup_commit_reference(sha1);
+ if (!cmit)
+ usage(describe_usage);
+
if (!initialized) {
initialized = 1;
for_each_ref(get_name);It is preceded by a "git diff" header, that looks like this (when the -c option is used):
diff --combined file
or like this (when the --cc option is used):
diff --cc file
It is followed by one or more extended header lines (this example shows a merge with two parents):
index<hash>,<hash>..<hash>
mode<mode>,<mode>..<mode>
newfilemode<mode>
deletedfilemode<mode>,<mode>
The mode <mode>,<mode>..<mode> line appears only if at least one of the <mode> is different from the rest. Extended headers with information about detected content movement (renames and copying detection) are designed to work with the diff of two <tree-ish> and are not used by combined diff format.
It is followed by a two-line from-file/to-file header:
--- a/file +++ b/file
Similar to the two-line header for the traditional unified diff format, /dev/null is used to signal created or deleted files.
However, if the --combined-all-paths option is provided, instead of a two-line from-file/to-file, you get an N+1 line from-file/to-file header, where N is the number of parents in the merge commit:
--- a/file --- a/file --- a/file +++ b/file
This extended format can be useful if rename or copy detection is active, to allow you to see the original name of the file in different parents.
Chunk header format is modified to prevent people from accidentally feeding it to patch -p1. Combined diff format was created for review of merge commit changes, and was not meant to be applied. The change is similar to the change in the extended index header:
@@@ <from-file-range> <from-file-range> <to-file-range> @@@
There are (number of parents + 1) @ characters in the chunk header for combined diff format.
Unlike the traditional unified diff format, which shows two files A and B with a single column that has - (minus -- appears in A but removed in B), + (plus -- missing in A but added to B), or " " (space -- unchanged) prefix, this format compares two or more files file1, file2,… with one file X, and shows how X differs from each of fileN. One column for each of fileN is prepended to the output line to note how X's line is different from it.
A - character in the column N means that the line appears in fileN but it does not appear in the result. A + character in the column N means that the line appears in the result, and fileN does not have that line (in other words, the line was added, from the point of view of that parent).
In the above example output, the function signature was changed from both files (hence two - removals from both file1 and file2, plus ++ to mean one line that was added does not appear in either file1 or file2). Also, eight other lines are the same from file1 but do not appear in file2 (hence prefixed with +).
When shown by git diff-tree -c, it compares the parents of a merge commit with the merge result (i.e. file1..fileN are the parents). When shown by git diff-files -c, it compares the two unresolved merge parents with the working tree file (i.e. file1 is stage 2 aka "our version", file2 is stage 3 aka "their version").
The --summary option describes newly added, deleted, renamed and copied files. The --stat option adds diffstat(1) graph to the output. These options can be combined with other options, such as -p, and are meant for human consumption.
When showing a change that involves a rename or a copy, --stat output formats the pathnames compactly by combining common prefix and suffix of the pathnames. For example, a change that moves arch/i386/Makefile to arch/x86/Makefile while modifying 4 lines will be shown like this:
arch/{i386 => x86}/Makefile | 4 +--The --numstat option gives the diffstat(1) information but is designed for easier machine consumption. An entry in --numstat output looks like this:
1 2 README
3 1 arch/{i386 => x86}/MakefileThat is, from left to right:
When -z output option is in effect, the output is formatted this way:
1 2 README NUL 3 1 NUL arch/i386/Makefile NUL arch/x86/Makefile NUL
That is:
The extra NUL before the preimage path in renamed case is to allow scripts that read the output to tell if the current record being read is a single-path record or a rename/copy record without reading ahead. After reading added and deleted lines, reading up to NUL would yield the pathname, but if that is NUL, the record will show two paths.
Part of the the section called “git(1)” suite
gitdiff[<options>] [<commit>] [--] [<path>…]
gitdiff[<options>]--cached[--merge-base] [<commit>] [--] [<path>…]
gitdiff[<options>] [--merge-base] <commit> [<commit>…] <commit> [--] [<path>…]
gitdiff[<options>] <commit>…<commit> [--] [<path>…]
gitdiff[<options>] <blob> <blob>
gitdiff[<options>]--no-index[--] <path> <path>
Show changes between the working tree and the index or a tree, changes between the index and a tree, changes between two trees, changes resulting from a merge, changes between two blob objects, or changes between two files on disk.
This form is to view the changes you staged for the next commit relative to the named <commit>. Typically you would want comparison with the latest commit, so if you do not give <commit>, it defaults to HEAD. If HEAD does not exist (e.g. unborn branches) and <commit> is not given, it shows all staged changes. --staged is a synonym of --cached.
If --merge-base is given, instead of using <commit>, use the merge base of <commit> and HEAD. git diff --cached --merge-base A is equivalent to git diff --cached $(git merge-base A HEAD).
This form is to view the changes you have in your working tree relative to the named <commit>. You can use HEAD to compare it with the latest commit, or a branch name to compare with the tip of a different branch.
If --merge-base is given, instead of using <commit>, use the merge base of <commit> and HEAD. git diff --merge-base A is equivalent to git diff $(git merge-base A HEAD).
This is to view the changes between two arbitrary <commit>.
If --merge-base is given, use the merge base of the two commits for the "before" side. git diff --merge-base A B is equivalent to git diff $(git merge-base A B) B.
Just in case you are doing something exotic, it should be noted that all of the <commit> in the above description, except in the --merge-base case and in the last two forms that use .. notations, can be any <tree>. A tree of interest is the one pointed to by the ref named AUTO_MERGE, which is written by the ort merge strategy upon hitting merge conflicts (see the section called “git-merge(1)”). Comparing the working tree with AUTO_MERGE shows changes you've made so far to resolve textual conflicts (see the examples below).
For a more complete list of ways to spell <commit>, see "SPECIFYING REVISIONS" section in the section called “gitrevisions(7)”. However, diff is about comparing two endpoints, not ranges, and the range notations (<commit>..<commit> and <commit>...<commit>) do not mean a range as defined in the "SPECIFYING RANGES" section in the section called “gitrevisions(7)”.
Generate a diff using the "anchored diff" algorithm.
This option may be specified more than once.
If a line exists in both the source and destination, exists only once, and starts with <text>, this algorithm attempts to prevent it from appearing as a deletion or addition in the output. It uses the "patience diff" algorithm internally.
Choose a diff algorithm. The variants are as follows:
For instance, if you configured the diff.algorithm variable to a non-default value and want to use the default one, then you have to use --diff-algorithm=default option.
Generate a diffstat. By default, as much space as necessary will be used for the filename part, and the rest for the graph part. Maximum width defaults to terminal width, or 80 columns if not connected to a terminal, and can be overridden by <width>. The width of the filename part can be limited by giving another width <name-width> after a comma or by setting diff.statNameWidth=<name-width>. The width of the graph part can be limited by using --stat-graph-width=<graph-width> or by setting diff.statGraphWidth=<graph-width>. Using --stat or --stat-graph-width affects all commands generating a stat graph, while setting diff.statNameWidth or diff.statGraphWidth does not affect git format-patch. By giving a third parameter <count>, you can limit the output to the first <count> lines, followed by ... if there are more.
These parameters can also be set individually with --stat-width=<width>, --stat-name-width=<name-width> and --stat-count=<count>.
Output the distribution of relative amount of changes for each sub-directory. The behavior of --dirstat can be customized by passing it a comma separated list of parameters. The defaults are controlled by the diff.dirstat configuration variable (see the section called “git-config(1)”). The following parameters are available:
Example: The following will count changed files, while ignoring directories with less than 10% of the total amount of changed files, and accumulating child directory counts in the parent directories: --dirstat=files,10,cumulative.
When --raw, --numstat, --name-only or --name-status has been given, do not munge pathnames and use NULs as output field terminators.
Without this option, pathnames with "unusual" characters are quoted as explained for the configuration variable core.quotePath (see the section called “git-config(1)”).
Moved lines of code are colored differently. It can be changed by the diff.colorMoved configuration setting. The <mode> defaults to no if the option is not given and to zebra if the option with no mode is given. The mode must be one of:
This configures how whitespace is ignored when performing the move detection for --color-moved. It can be set by the diff.colorMovedWS configuration setting. These modes can be given as a comma separated list:
By default, words are delimited by whitespace; see --word-diff-regex below. The <mode> defaults to plain, and must be one of:
[-removed-] and {added}. Makes no
attempts to escape the delimiters if they appear in the input,
so the output may be ambiguous.
Note that despite the name of the first mode, color is used to highlight the changed parts in all modes if enabled.
Use <regex> to decide what a word is, instead of considering runs of non-whitespace to be a word. Also implies --word-diff unless it was already enabled.
Every non-overlapping match of the <regex> is considered a word. Anything between these matches is considered whitespace and ignored(!) for the purposes of finding differences. You may want to append |[^[:space:]] to your regular expression to make sure that it matches all non-whitespace characters. A match that contains a newline is silently truncated(!) at the newline.
For example, --word-diff-regex=. will treat each character as a word and, correspondingly, show differences character by character.
The regex can also be set via a diff driver or configuration option, see the section called “gitattributes(5)” or the section called “git-config(1)”. Giving it explicitly overrides any diff driver or configuration setting. Diff drivers override configuration settings.
Break complete rewrite changes into pairs of delete and create. This serves two purposes:
It affects the way a change that amounts to a total rewrite of a file not as a series of deletion and insertion mixed together with a very few lines that happen to match textually as the context, but as a single deletion of everything old followed by a single insertion of everything new, and the number <m> controls this aspect of the -B option (defaults to 60%). -B/70% specifies that less than 30% of the original should remain in the result for Git to consider it a total rewrite (i.e. otherwise the resulting patch will be a series of deletion and insertion mixed together with context lines).
When used with -M, a totally-rewritten file is also considered as the source of a rename (usually -M only considers a file that disappeared as the source of a rename), and the number <n> controls this aspect of the -B option (defaults to 50%). -B20% specifies that a change with addition and deletion compared to 20% or more of the file's size are eligible for being picked up as a possible source of a rename to another file.
Omit the preimage for deletes, i.e. print only the header but not the diff between the preimage and /dev/null. The resulting patch is not meant to be applied with patch or git apply; this is solely for people who want to just concentrate on reviewing the text after the change. In addition, the output obviously lacks enough information to apply such a patch in reverse, even manually, hence the name of the option.
When used together with -B, omit also the preimage in the deletion part of a delete/create pair.
Select only files that are Added (A), Copied (C), Deleted (D), Modified (M), Renamed (R), have their type (i.e. regular file, symlink, submodule, …) changed (T), are Unmerged (U), are Unknown (X), or have had their pairing Broken (B). Any combination of the filter characters (including none) can be used. When * (All-or-none) is added to the combination, all paths are selected if there is any file that matches other criteria in the comparison; if there is no file that matches other criteria, nothing is selected.
Also, these upper-case letters can be downcased to exclude. E.g. --diff-filter=ad excludes added and deleted paths.
Note that not all diffs can feature all types. For instance, copied and renamed entries cannot appear if detection for those types is disabled.
Look for differences that change the number of occurrences of the specified <string> (i.e. addition/deletion) in a file. Intended for the scripter's use.
It is useful when you're looking for an exact block of code (like a struct), and want to know the history of that block since it first came into being: use the feature iteratively to feed the interesting block in the preimage back into -S, and keep going until you get the very first version of the block.
Binary files are searched as well.
Look for differences whose patch text contains added/removed lines that match <regex>.
To illustrate the difference between -S<regex> --pickaxe-regex and -G<regex>, consider a commit with the following diff in the same file:
+ return frotz(nitfol, two->ptr, 1, 0); ... - hit = frotz(nitfol, mf2.ptr, 1, 0);
While git log -G"frotz\(nitfol" will show this commit, git log -S"frotz\(nitfol" --pickaxe-regex will not (because the number of occurrences of that string did not change).
Unless --text is supplied patches of binary files without a textconv filter will be ignored.
See the pickaxe entry in the section called “gitdiffcore(7)” for more information.
Look for differences that change the number of occurrences of the specified object. Similar to -S, just the argument is different in that it doesn't search for a specific string but for a specific object id.
The object can be a blob or a submodule commit. It implies the -t option in git-log to also find trees.
Control the order in which files appear in the output. This overrides the diff.orderFile configuration variable (see the section called “git-config(1)”). To cancel diff.orderFile, use -O/dev/null.
The output order is determined by the order of glob patterns in <orderfile>. All files with pathnames that match the first pattern are output first, all files with pathnames that match the second pattern (but not the first) are output next, and so on. All files with pathnames that do not match any pattern are output last, as if there was an implicit match-all pattern at the end of the file. If multiple pathnames have the same rank (they match the same pattern but no earlier patterns), their output order relative to each other is the normal order.
<orderfile> is parsed as follows:
Patterns have the same syntax and semantics as patterns used for fnmatch(3) without the FNM_PATHNAME flag, except a pathname also matches a pattern if removing any number of the final pathname components matches the pattern. For example, the pattern "foo*bar" matches "fooasdfbar" and "foo/bar/baz/asdf" but not "foobarx".
diff.<driver>.trustExitCode or
environment variable GIT_EXTERNAL_DIFF_TRUST_EXIT_CODE is
false.
For more detailed explanation on these common options, see also the section called “gitdiffcore(7)”.
Compare the working tree with
The index contains these stages only for unmerged entries i.e. while resolving conflicts. See the section called “git-read-tree(1)” section "3-Way Merge" for detailed information.
The raw output format from git-diff-index, git-diff-tree, git-diff-files and git diff --raw are very similar.
These commands all compare two sets of things; what is compared differs:
The git-diff-tree command begins its output by printing the hash of what is being compared. After that, all the commands print one output line per changed file.
An output line is formatted this way:
in-place edit :100644 100644 bcd1234 0123456 M file0 copy-edit :100644 100644 abcd123 1234567 C68 file1 file2 rename-edit :100644 100644 abcd123 1234567 R86 file1 file3 create :000000 100644 0000000 1234567 A file4 delete :100644 000000 1234567 0000000 D file5 unmerged :000000 000000 0000000 0000000 U file6
That is, from the left to the right:
Possible status letters are:
Status letters C and R are always followed by a score (denoting the percentage of similarity between the source and target of the move or copy). Status letter M may be followed by a score (denoting the percentage of dissimilarity) for file rewrites.
The sha1 for "dst" is shown as all 0's if a file on the filesystem is out of sync with the index.
Example:
:100644 100644 5be4a4a 0000000 M file.c
Without the -z option, pathnames with "unusual" characters are quoted as explained for the configuration variable core.quotePath (see the section called “git-config(1)”). Using -z the filename is output verbatim and the line is terminated by a NUL byte.
git-diff-tree, git-diff-files and git-diff --raw can take -c or --cc option to generate diff output also for merge commits. The output differs from the format described above in the following way:
For -c and --cc, only the destination or final path is shown even if the file was renamed on any side of history. With --combined-all-paths, the name of the path in each parent is shown followed by the name of the path in the merge commit.
Examples for -c and --cc without --combined-all-paths:
::100644 100644 100644 fabadb8 cc95eb0 4866510 MM desc.c ::100755 100755 100755 52b7a2d 6d1ac04 d2ac7d7 RM bar.sh ::100644 100644 100644 e07d6c5 9042e82 ee91881 RR phooey.c
Examples when --combined-all-paths added to either -c or --cc:
::100644 100644 100644 fabadb8 cc95eb0 4866510 MM desc.c desc.c desc.c ::100755 100755 100755 52b7a2d 6d1ac04 d2ac7d7 RM foo.sh bar.sh bar.sh ::100644 100644 100644 e07d6c5 9042e82 ee91881 RR fooey.c fuey.c phooey.c
Note that combined diff lists only files which were modified from all parents.
Running the section called “git-diff(1)”, the section called “git-log(1)”, the section called “git-show(1)”, the section called “git-diff-index(1)”, the section called “git-diff-tree(1)”, or the section called “git-diff-files(1)” with the -p option produces patch text. You can customize the creation of patch text via the GIT_EXTERNAL_DIFF and the GIT_DIFF_OPTS environment variables (see the section called “git(1)”), and the diff attribute (see the section called “gitattributes(5)”).
What the -p option produces is slightly different from the traditional diff format:
It is preceded by a "git diff" header that looks like this:
diff --git a/file1 b/file2
The a/ and b/ filenames are the same unless rename/copy is involved. Especially, even for a creation or a deletion, /dev/null is not used in place of the a/ or b/ filenames.
When a rename/copy is involved, file1 and file2 show the name of the source file of the rename/copy and the name of the file that the rename/copy produces, respectively.
It is followed by one or more extended header lines:
oldmode<mode>
newmode<mode>
deletedfilemode<mode>
newfilemode<mode>
copyfrom<path>
copyto<path>
renamefrom<path>
renameto<path>
similarityindex<number>
dissimilarityindex<number>
index<hash>..<hash> <mode>
File modes <mode> are printed as 6-digit octal numbers including the file type and file permission bits.
Path names in extended headers do not include the a/ and b/ prefixes.
The similarity index is the percentage of unchanged lines, and the dissimilarity index is the percentage of changed lines. It is a rounded down integer, followed by a percent sign. The similarity index value of 100% is thus reserved for two equal files, while 100% dissimilarity means that no line from the old file made it into the new one.
The index line includes the blob object names before and after the change. The <mode> is included if the file mode does not change; otherwise, separate lines indicate the old and the new mode.
All the file1 files in the output refer to files before the commit, and all the file2 files refer to files after the commit. It is incorrect to apply each change to each file sequentially. For example, this patch will swap a and b:
diff --git a/a b/b rename from a rename to b diff --git a/b b/a rename from b rename to a
Any diff-generating command can take the -c or --cc option to produce a combined diff when showing a merge. This is the default format when showing merges with the section called “git-diff(1)” or the section called “git-show(1)”. Note also that you can give suitable --diff-merges option to any of these commands to force generation of diffs in a specific format.
A "combined diff" format looks like this:
diff --combined describe.c
index fabadb8,cc95eb0..4866510
--- a/describe.c
+++ b/describe.c
@@@ -98,20 -98,12 +98,20 @@@
return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1;
}
- static void describe(char *arg)
-static void describe(struct commit *cmit, int last_one)
++static void describe(char *arg, int last_one)
{
+ unsigned char sha1[20];
+ struct commit *cmit;
struct commit_list *list;
static int initialized = 0;
struct commit_name *n;
+ if (get_sha1(arg, sha1) < 0)
+ usage(describe_usage);
+ cmit = lookup_commit_reference(sha1);
+ if (!cmit)
+ usage(describe_usage);
+
if (!initialized) {
initialized = 1;
for_each_ref(get_name);It is preceded by a "git diff" header, that looks like this (when the -c option is used):
diff --combined file
or like this (when the --cc option is used):
diff --cc file
It is followed by one or more extended header lines (this example shows a merge with two parents):
index<hash>,<hash>..<hash>
mode<mode>,<mode>..<mode>
newfilemode<mode>
deletedfilemode<mode>,<mode>
The mode <mode>,<mode>..<mode> line appears only if at least one of the <mode> is different from the rest. Extended headers with information about detected content movement (renames and copying detection) are designed to work with the diff of two <tree-ish> and are not used by combined diff format.
It is followed by a two-line from-file/to-file header:
--- a/file +++ b/file
Similar to the two-line header for the traditional unified diff format, /dev/null is used to signal created or deleted files.
However, if the --combined-all-paths option is provided, instead of a two-line from-file/to-file, you get an N+1 line from-file/to-file header, where N is the number of parents in the merge commit:
--- a/file --- a/file --- a/file +++ b/file
This extended format can be useful if rename or copy detection is active, to allow you to see the original name of the file in different parents.
Chunk header format is modified to prevent people from accidentally feeding it to patch -p1. Combined diff format was created for review of merge commit changes, and was not meant to be applied. The change is similar to the change in the extended index header:
@@@ <from-file-range> <from-file-range> <to-file-range> @@@
There are (number of parents + 1) @ characters in the chunk header for combined diff format.
Unlike the traditional unified diff format, which shows two files A and B with a single column that has - (minus -- appears in A but removed in B), + (plus -- missing in A but added to B), or " " (space -- unchanged) prefix, this format compares two or more files file1, file2,… with one file X, and shows how X differs from each of fileN. One column for each of fileN is prepended to the output line to note how X's line is different from it.
A - character in the column N means that the line appears in fileN but it does not appear in the result. A + character in the column N means that the line appears in the result, and fileN does not have that line (in other words, the line was added, from the point of view of that parent).
In the above example output, the function signature was changed from both files (hence two - removals from both file1 and file2, plus ++ to mean one line that was added does not appear in either file1 or file2). Also, eight other lines are the same from file1 but do not appear in file2 (hence prefixed with +).
When shown by git diff-tree -c, it compares the parents of a merge commit with the merge result (i.e. file1..fileN are the parents). When shown by git diff-files -c, it compares the two unresolved merge parents with the working tree file (i.e. file1 is stage 2 aka "our version", file2 is stage 3 aka "their version").
The --summary option describes newly added, deleted, renamed and copied files. The --stat option adds diffstat(1) graph to the output. These options can be combined with other options, such as -p, and are meant for human consumption.
When showing a change that involves a rename or a copy, --stat output formats the pathnames compactly by combining common prefix and suffix of the pathnames. For example, a change that moves arch/i386/Makefile to arch/x86/Makefile while modifying 4 lines will be shown like this:
arch/{i386 => x86}/Makefile | 4 +--The --numstat option gives the diffstat(1) information but is designed for easier machine consumption. An entry in --numstat output looks like this:
1 2 README
3 1 arch/{i386 => x86}/MakefileThat is, from left to right:
When -z output option is in effect, the output is formatted this way:
1 2 README NUL 3 1 NUL arch/i386/Makefile NUL arch/x86/Makefile NUL
That is:
The extra NUL before the preimage path in renamed case is to allow scripts that read the output to tell if the current record being read is a single-path record or a rename/copy record without reading ahead. After reading added and deleted lines, reading up to NUL would yield the pathname, but if that is NUL, the record will show two paths.
$ git diff$ git diff --cached
$ git diff HEAD
$ git diff AUTO_MERGE
Changes in the working tree not yet staged for the next commit. | |
Changes between the index and your last commit; what you would be committing if you run git commit without -a option. | |
Changes in the working tree since your last commit; what you would be committing if you run git commit -a | |
Changes in the working tree you've made to resolve textual conflicts so far. |
$ git diff test$ git diff HEAD -- ./test
$ git diff HEAD^ HEAD
$ git diff topic master$ git diff topic..master
$ git diff topic...master
$ git diff --diff-filter=MRC$ git diff --name-status
$ git diff arch/i386 include/asm-i386
$ git diff --find-copies-harder -B -C$ git diff -R
Everything below this line in this section is selectively included from the the section called “git-config(1)” documentation. The content is the same as what's found there:
A comma separated list of --dirstat parameters specifying the default behavior of the --dirstat option to git diff and friends. The defaults can be overridden on the command line (using --dirstat=<param>,...). The fallback defaults (when not changed by diff.dirstat) are changes,noncumulative,3. The following parameters are available:
Example: The following will count changed files, while ignoring directories with less than 10% of the total amount of changed files, and accumulating child directory counts in the parent directories: files,10,cumulative.
If set, git diff uses a prefix pair that is different from the standard a/ and b/ depending on what is being compared. When this configuration is in effect, reverse diff output also swaps the order of the prefixes:
Choose a diff algorithm. The variants are as follows:
diff(1), the section called “git-difftool(1)”, the section called “git-log(1)”, the section called “gitdiffcore(7)”, the section called “git-format-patch(1)”, the section called “git-apply(1)”, the section called “git-show(1)”
Part of the the section called “git(1)” suite
git difftool is a Git command that allows you to compare and edit files between revisions using common diff tools. git difftool is a frontend to git diff and accepts the same options and arguments. See the section called “git-diff(1)”.
Use the diff tool specified by <tool>. Valid values include emerge, kompare, meld, and vimdiff. Run git difftool --tool-help for the list of valid <tool> settings.
If a diff tool is not specified, git difftool will use the configuration variable diff.tool. If the configuration variable diff.tool is not set, git difftool will pick a suitable default.
You can explicitly provide a full path to the tool by setting the configuration variable difftool.<tool>.path. For example, you can configure the absolute path to kdiff3 by setting difftool.kdiff3.path. Otherwise, git difftool assumes the tool is available in PATH.
Instead of running one of the known diff tools, git difftool can be customized to run an alternative program by specifying the command line to invoke in a configuration variable difftool.<tool>.cmd.
When git difftool is invoked with this tool (either through the -t or --tool option or the diff.tool configuration variable) the configured command line will be invoked with the following variables available: $LOCAL is set to the name of the temporary file containing the contents of the diff pre-image and $REMOTE is set to the name of the temporary file containing the contents of the diff post-image. $MERGED is the name of the file which is being compared. $BASE is provided for compatibility with custom merge tool commands and has the same value as $MERGED.
git difftool's default behavior is to create symlinks to the working tree when run in --dir-diff mode and the right-hand side of the comparison yields the same content as the file in the working tree.
Specifying --no-symlinks instructs git difftool to create copies instead. --no-symlinks is the default on Windows.
Errors reported by the diff tool are ignored by default. Use --trust-exit-code to make git-difftool exit when an invoked diff tool returns a non-zero exit code.
git-difftool will forward the exit code of the invoked tool when --trust-exit-code is used.
See the section called “git-diff(1)” for the full list of supported options.
git difftool falls back to git mergetool config variables when the difftool equivalents have not been defined.
Everything above this line in this section isn't included from the the section called “git-config(1)” documentation. The content that follows is the same as what's found there:
Controls which diff tool is used by the section called “git-difftool(1)” when the -g/--gui flag is specified. This variable overrides the value configured in merge.guitool. The list below shows the valid built-in values. Any other value is treated as a custom diff tool and requires that a corresponding difftool.<guitool>.cmd variable is defined.
Specify the command to invoke the specified diff tool. The specified command is evaluated in shell with the following variables available: LOCAL is set to the name of the temporary file containing the contents of the diff pre-image and REMOTE is set to the name of the temporary file containing the contents of the diff post-image.
See the --tool=<tool> option in the section called “git-difftool(1)” for more details.
Exit difftool if the invoked diff tool returns a non-zero exit status.
See the --trust-exit-code option in the section called “git-difftool(1)” for more details.
Part of the the section called “git(1)” suite
This program dumps the given revisions in a form suitable to be piped into git fast-import.
You can use it as a human-readable bundle replacement (see the section called “git-bundle(1)”), or as a format that can be edited before being fed to git fast-import in order to do history rewrites (an ability relied on by tools like git filter-repo).
Specify how to handle signed tags. Since any transformation after the export (or during the export, such as excluding revisions) can change the hashes being signed, the signatures may become invalid.
When asking to abort (which is the default), this program will die when encountering a signed tag. With strip, the tags will silently be made unsigned, with warn-strip they will be made unsigned but a warning will be displayed, with verbatim, they will be silently exported and with warn-verbatim (or warn, a deprecated synonym), they will be exported, but you will see a warning. verbatim and warn-verbatim should only be used if you know that no transformation affecting tags or any commit in their history will be performed by you or by fast-export or fast-import, or if you do not care that the resulting tag will have an invalid signature.
Specify how to handle signed commits. Behaves exactly as --signed-tags, but for commits. Default is strip, which is the same as how earlier versions of this command without this option behaved.
This is highly experimental and the format of the data stream may change in the future without compatibility guarantees.
Specify how to handle tags whose tagged object is filtered out. Since revisions and files to export can be limited by path, tagged objects may be filtered completely.
When asking to abort (which is the default), this program will die when encountering such a tag. With drop it will omit such tags from the output. With rewrite, if the tagged object is a commit, it will rewrite the tag to tag an ancestor commit (via parent rewriting; see the section called “git-rev-list(1)”).
Perform move and/or copy detection, as described in the the section called “git-diff(1)” manual page, and use it to generate rename and copy commands in the output dump.
Note that earlier versions of this command did not complain and produced incorrect results if you gave these options.
In addition to labelling blobs and commits with mark ids, also label tags. This is useful in conjunction with --export-marks and --import-marks, and is also useful (and necessary) for exporting of nested tags. It does not hurt other cases and would be the default, but many fast-import frontends are not prepared to accept tags with mark identifiers.
Any commits (or tags) that have already been marked will not be exported again. If the backend uses a similar --import-marks file, this allows for incremental bidirectional exporting of the repository by keeping the marks the same across runs.
$ git fast-export --all | (cd /empty/repository && git fast-import)
This will export the whole repository and import it into the existing empty repository. Except for reencoding commits that are not in UTF-8, it would be a one-to-one mirror.
$ git fast-export master~5..master |
sed "s|refs/heads/master|refs/heads/other|" |
git fast-importThis makes a new branch called other from master~5..master (i.e. if master has linear history, it will take the last 5 commits).
Note that this assumes that none of the blobs and commit messages referenced by that revision range contains the string refs/heads/master.
If the --anonymize option is given, git will attempt to remove all identifying information from the repository while still retaining enough of the original tree and history patterns to reproduce some bugs. The goal is that a git bug which is found on a private repository will persist in the anonymized repository, and the latter can be shared with git developers to help solve the bug.
With this option, git will replace all refnames, paths, blob contents, commit and tag messages, names, and email addresses in the output with anonymized data. Two instances of the same string will be replaced equivalently (e.g., two commits with the same author will have the same anonymized author in the output, but bear no resemblance to the original author string). The relationship between commits, branches, and tags is retained, as well as the commit timestamps (but the commit messages and refnames bear no resemblance to the originals). The relative makeup of the tree is retained (e.g., if you have a root tree with 10 files and 3 trees, so will the output), but their names and the contents of the files will be replaced.
If you think you have found a git bug, you can start by exporting an anonymized stream of the whole repository:
$ git fast-export --anonymize --all >anon-stream
Then confirm that the bug persists in a repository created from that stream (many bugs will not, as they really do depend on the exact repository contents):
$ git init anon-repo $ cd anon-repo $ git fast-import <../anon-stream $ ... test your bug ...
If the anonymized repository shows the bug, it may be worth sharing anon-stream along with a regular bug report. Note that the anonymized stream compresses very well, so gzipping it is encouraged. If you want to examine the stream to see that it does not contain any private data, you can peruse it directly before sending. You may also want to try:
$ perl -pe 's/\d+/X/g' <anon-stream | sort -u | less
which shows all of the unique lines (with numbers converted to "X", to collapse "User 0", "User 1", etc into "User X"). This produces a much smaller output, and it is usually easy to quickly confirm that there is no private data in the stream.
Reproducing some bugs may require referencing particular commits or paths, which becomes challenging after refnames and paths have been anonymized. You can ask for a particular token to be left as-is or mapped to a new value. For example, if you have a bug which reproduces with git rev-list sensitive -- secret.c, you can run:
$ git fast-export --anonymize --all \
--anonymize-map=sensitive:foo \
--anonymize-map=secret.c:bar.c \
>streamAfter importing the stream, you can then run git rev-list foo -- bar.c in the anonymized repository.
Note that paths and refnames are split into tokens at slash boundaries. The command above would anonymize subdir/secret.c as something like path123/bar.c; you could then search for bar.c in the anonymized repository to determine the final pathname.
To make referencing the final pathname simpler, you can map each path component; so if you also anonymize subdir to publicdir, then the final pathname would be publicdir/bar.c.
Since git fast-import cannot tag trees, you will not be able to export the linux.git repository completely, as it contains a tag referencing a tree instead of a commit.
Part of the the section called “git(1)” suite
This program is usually not what the end user wants to run directly. Most end users want to use one of the existing frontend programs, which parses a specific type of foreign source and feeds the contents stored there to git fast-import.
fast-import reads a mixed command/data stream from standard input and writes one or more packfiles directly into the current repository. When EOF is received on standard input, fast import writes out updated branch and tag refs, fully updating the current repository with the newly imported data.
The fast-import backend itself can import into an empty repository (one that has already been initialized by git init) or incrementally update an existing populated repository. Whether or not incremental imports are supported from a particular foreign source depends on the frontend program in use.
Many command-line options can be provided as part of the fast-import stream itself by using the feature or option commands. However, some of these options are unsafe (e.g., allowing fast-import to access the filesystem outside of the repository). These options are disabled by default, but can be allowed by providing this option on the command line. This currently impacts only the export-marks, import-marks, and import-marks-if-exists feature commands.
Only enable this option if you trust the program generating the fast-import stream! This option is enabled automatically for remote-helpers that use the `import` capability, as they are already trusted to run their own code.
After specifying --relative-marks the paths specified with --import-marks= and --export-marks= are relative to an internal directory in the current repository. In git-fast-import this means that the paths are relative to the .git/info/fast-import directory. However, other importers may use a different location.
Relative and non-relative marks may be combined by interweaving --(no-)-relative-marks with the --(import|export)-marks= options.
Rewrite the object IDs for the submodule specified by <name> from the values used in the from <file> to those used in the to <file>. The from marks should have been created by git fast-export, and the to marks should have been created by git fast-import when importing that same submodule.
<name> may be any arbitrary string not containing a colon character, but the same value must be used with both options when specifying corresponding marks. Multiple submodules may be specified with different values for <name>. It is an error not to use these options in corresponding pairs.
These options are primarily useful when converting a repository from one hash algorithm to another; without them, fast-import will fail if it encounters a submodule because it has no way of writing the object ID into the new hash algorithm.
The design of fast-import allows it to import large projects in a minimum amount of memory usage and processing time. Assuming the frontend is able to keep up with fast-import and feed it a constant stream of data, import times for projects holding 10+ years of history and containing 100,000+ individual commits are generally completed in just 1-2 hours on quite modest (~$2,000 USD) hardware.
Most bottlenecks appear to be in foreign source data access (the source just cannot extract revisions fast enough) or disk IO (fast-import writes as fast as the disk will take the data). Imports will run faster if the source data is stored on a different drive than the destination Git repository (due to less IO contention).
A typical frontend for fast-import tends to weigh in at approximately 200 lines of Perl/Python/Ruby code. Most developers have been able to create working importers in just a couple of hours, even though it is their first exposure to fast-import, and sometimes even to Git. This is an ideal situation, given that most conversion tools are throw-away (use once, and never look back).
Like git push or git fetch, imports handled by fast-import are safe to run alongside parallel git repack -a -d or git gc invocations, or any other Git operation (including git prune, as loose objects are never used by fast-import).
fast-import does not lock the branch or tag refs it is actively importing. After the import, during its ref update phase, fast-import tests each existing branch ref to verify the update will be a fast-forward update (the commit stored in the ref is contained in the new history of the commit to be written). If the update is not a fast-forward update, fast-import will skip updating that ref and instead prints a warning message. fast-import will always attempt to update all branch refs, and does not stop on the first failure.
Branch updates can be forced with --force, but it's recommended that this only be used on an otherwise quiet repository. Using --force is not necessary for an initial import into an empty repository.
fast-import tracks a set of branches in memory. Any branch can be created or modified at any point during the import process by sending a commit command on the input stream. This design allows a frontend program to process an unlimited number of branches simultaneously, generating commits in the order they are available from the source data. It also simplifies the frontend programs considerably.
fast-import does not use or alter the current working directory, or any file within it. (It does however update the current Git repository, as referenced by GIT_DIR.) Therefore an import frontend may use the working directory for its own purposes, such as extracting file revisions from the foreign source. This ignorance of the working directory also allows fast-import to run very quickly, as it does not need to perform any costly file update operations when switching between branches.
With the exception of raw file data (which Git does not interpret) the fast-import input format is text (ASCII) based. This text based format simplifies development and debugging of frontend programs, especially when a higher level language such as Perl, Python or Ruby is being used.
fast-import is very strict about its input. Where we say SP below we mean exactly one space. Likewise LF means one (and only one) linefeed and HT one (and only one) horizontal tab. Supplying additional whitespace characters will cause unexpected results, such as branch names or file names with leading or trailing spaces in their name, or early termination of fast-import when it encounters unexpected input.
To aid in debugging frontends fast-import ignores any line that begins with # (ASCII pound/hash) up to and including the line ending LF. A comment line may contain any sequence of bytes that does not contain an LF and therefore may be used to include any detailed debugging information that might be specific to the frontend and useful when inspecting a fast-import data stream.
The following date formats are supported. A frontend should select the format it will use for this import by passing the format name in the --date-format=<fmt> command-line option.
This is the Git native format and is <time> SP <offutc>. It is also fast-import's default format, if --date-format was not specified.
The time of the event is specified by <time> as the number of seconds since the UNIX epoch (midnight, Jan 1, 1970, UTC) and is written as an ASCII decimal integer.
The local offset is specified by <offutc> as a positive or negative offset from UTC. For example EST (which is 5 hours behind UTC) would be expressed in <tz> by -0500 while UTC is +0000. The local offset does not affect <time>; it is used only as an advisement to help formatting routines display the timestamp.
If the local offset is not available in the source material, use +0000, or the most common local offset. For example many organizations have a CVS repository which has only ever been accessed by users who are located in the same location and time zone. In this case a reasonable offset from UTC could be assumed.
Unlike the rfc2822 format, this format is very strict. Any variation in formatting will cause fast-import to reject the value, and some sanity checks on the numeric values may also be performed.
This is the standard date format as described by RFC 2822.
An example value is Tue Feb 6 11:22:18 2007 -0500. The Git parser is accurate, but a little on the lenient side. It is the same parser used by git am when applying patches received from email.
Some malformed strings may be accepted as valid dates. In some of these cases Git will still be able to obtain the correct date from the malformed string. There are also some types of malformed strings which Git will parse wrong, and yet consider valid. Seriously malformed strings will be rejected.
Unlike the raw format above, the time zone/UTC offset information contained in an RFC 2822 date string is used to adjust the date value to UTC prior to storage. Therefore it is important that this information be as accurate as possible.
If the source material uses RFC 2822 style dates, the frontend should let fast-import handle the parsing and conversion (rather than attempting to do it itself) as the Git parser has been well tested in the wild.
Frontends should prefer the raw format if the source material already uses UNIX-epoch format, can be coaxed to give dates in that format, or its format is easily convertible to it, as there is no ambiguity in parsing.
Always use the current time and time zone. The literal now must always be supplied for <when>.
This is a toy format. The current time and time zone of this system is always copied into the identity string at the time it is being created by fast-import. There is no way to specify a different time or time zone.
This particular format is supplied as it's short to implement and may be useful to a process that wants to create a new commit right now, without needing to use a working directory or git update-index.
If separate author and committer commands are used in a commit the timestamps may not match, as the system clock will be polled twice (once for each command). The only way to ensure that both author and committer identity information has the same timestamp is to omit author (thus copying from committer) or to use a date format other than now.
fast-import accepts several commands to update the current repository and control the current import process. More detailed discussion (with examples) of each command follows later.
Create or update a branch with a new commit, recording one logical change to the project.
'commit' SP <ref> LF
mark?
original-oid?
('author' (SP <name>)? SP LT <email> GT SP <when> LF)?
'committer' (SP <name>)? SP LT <email> GT SP <when> LF
('gpgsig' SP <alg> LF data)?
('encoding' SP <encoding> LF)?
data
('from' SP <commit-ish> LF)?
('merge' SP <commit-ish> LF)*
(filemodify | filedelete | filecopy | filerename | filedeleteall | notemodify)*
LF?where <ref> is the name of the branch to make the commit on. Typically branch names are prefixed with refs/heads/ in Git, so importing the CVS branch symbol RELENG-1_0 would use refs/heads/RELENG-1_0 for the value of <ref>. The value of <ref> must be a valid refname in Git. As LF is not valid in a Git refname, no quoting or escaping syntax is supported here.
A mark command may optionally appear, requesting fast-import to save a reference to the newly created commit for future use by the frontend (see below for format). It is very common for frontends to mark every commit they create, thereby allowing future branch creation from any imported commit.
The data command following committer must supply the commit message (see below for data command syntax). To import an empty commit message use a 0 length data. Commit messages are free-form and are not interpreted by Git. Currently they must be encoded in UTF-8, as fast-import does not permit other encodings to be specified.
Zero or more filemodify, filedelete, filecopy, filerename, filedeleteall and notemodify commands may be included to update the contents of the branch prior to creating the commit. These commands may be supplied in any order. However it is recommended that a filedeleteall command precede all filemodify, filecopy, filerename and notemodify commands in the same commit, as filedeleteall wipes the branch clean (see below).
The LF after the command is optional (it used to be required). Note that for reasons of backward compatibility, if the commit ends with a data command (i.e. it has no from, merge, filemodify, filedelete, filecopy, filerename, filedeleteall or notemodify commands) then two LF commands may appear at the end of the command instead of just one.
An author command may optionally appear, if the author information might differ from the committer information. If author is omitted then fast-import will automatically use the committer's information for the author portion of the commit. See below for a description of the fields in author, as they are identical to committer.
The committer command indicates who made this commit, and when they made it.
Here <name> is the person's display name (for example Com M Itter) and <email> is the person's email address (cm@example.com). LT and GT are the literal less-than (\x3c) and greater-than (\x3e) symbols. These are required to delimit the email address from the other fields in the line. Note that <name> and <email> are free-form and may contain any sequence of bytes, except LT, GT and LF. <name> is typically UTF-8 encoded.
The time of the change is specified by <when> using the date format that was selected by the --date-format=<fmt> command-line option. See Date Formats above for the set of supported formats, and their syntax.
The optional gpgsig command is used to include a PGP/GPG signature that signs the commit data.
Here <alg> specifies which hashing algorithm is used for this signature, either sha1 or sha256.
This is highly experimental and the format of the data stream may change in the future without compatibility guarantees.
The optional encoding command indicates the encoding of the commit message. Most commits are UTF-8 and the encoding is omitted, but this allows importing commit messages into git without first reencoding them.
The from command is used to specify the commit to initialize this branch from. This revision will be the first ancestor of the new commit. The state of the tree built at this commit will begin with the state at the from commit, and be altered by the content modifications in this commit.
Omitting the from command in the first commit of a new branch will cause fast-import to create that commit with no ancestor. This tends to be desired only for the initial commit of a project. If the frontend creates all files from scratch when making a new branch, a merge command may be used instead of from to start the commit with an empty tree. Omitting the from command on existing branches is usually desired, as the current commit on that branch is automatically assumed to be the first ancestor of the new commit.
As LF is not valid in a Git refname or SHA-1 expression, no quoting or escaping syntax is supported within <commit-ish>.
Here <commit-ish> is any of the following:
A mark reference, :<idnum>, where <idnum> is the mark number.
The reason fast-import uses : to denote a mark reference is this character is not legal in a Git branch name. The leading : makes it easy to distinguish between the mark 42 (:42) and the branch 42 (42 or refs/heads/42), or an abbreviated SHA-1 which happened to consist only of base-10 digits.
Marks must be declared (via mark) before they can be used.
The special case of restarting an incremental import from the current branch value should be written as:
from refs/heads/branch^0
The ^0 suffix is necessary as fast-import does not permit a branch to start from itself, and the branch is created in memory before the from command is even read from the input. Adding ^0 will force fast-import to resolve the commit through Git's revision parsing library, rather than its internal branch table, thereby loading in the existing value of the branch.
Includes one additional ancestor commit. The additional ancestry link does not change the way the tree state is built at this commit. If the from command is omitted when creating a new branch, the first merge commit will be the first ancestor of the current commit, and the branch will start out with no files. An unlimited number of merge commands per commit are permitted by fast-import, thereby establishing an n-way merge.
Here <commit-ish> is any of the commit specification expressions also accepted by from (see above).
Included in a commit command to add a new file or change the content of an existing file. This command has two different means of specifying the content of the file.
The data content for the file was already supplied by a prior blob command. The frontend just needs to connect it.
'M' SP <mode> SP <dataref> SP <path> LF
Here usually <dataref> must be either a mark reference (:<idnum>) set by a prior blob command, or a full 40-byte SHA-1 of an existing Git blob object. If <mode> is 040000` then <dataref> must be the full 40-byte SHA-1 of an existing Git tree object or a mark reference set with --import-marks.
The data content for the file has not been supplied yet. The frontend wants to supply it as part of this modify command.
'M' SP <mode> SP 'inline' SP <path> LF
dataSee below for a detailed description of the data command.
In both formats <mode> is the type of file entry, specified in octal. Git only supports the following modes:
In both formats <path> is the complete path of the file to be added (if not already existing) or modified (if already existing).
A <path> can be written as unquoted bytes or a C-style quoted string.
When a <path> does not start with a double quote ("), it is an unquoted string and is parsed as literal bytes without any escape sequences. However, if the filename contains LF or starts with double quote, it cannot be represented as an unquoted string and must be quoted. Additionally, the source <path> in filecopy or filerename must be quoted if it contains SP.
When a <path> starts with a double quote ("), it is a C-style quoted string, where the complete filename is enclosed in a pair of double quotes and escape sequences are used. Certain characters must be escaped by preceding them with a backslash: LF is written as \n, backslash as \\, and double quote as \". Some characters may optionally be written with escape sequences: \a for bell, \b for backspace, \f for form feed, \n for line feed, \r for carriage return, \t for horizontal tab, and \v for vertical tab. Any byte can be written with 3-digit octal codes (e.g., \033). All filenames can be represented as quoted strings.
A <path> must use UNIX-style directory separators (forward slash /) and its value must be in canonical form. That is it must not:
The root of the tree can be represented by an empty string as <path>.
<path> cannot contain NUL, either literally or escaped as \000. It is recommended that <path> always be encoded using UTF-8.
Included in a commit command to remove a file or recursively delete an entire directory from the branch. If the file or directory removal makes its parent directory empty, the parent directory will be automatically removed too. This cascades up the tree until the first non-empty directory or the root is reached.
'D' SP <path> LF
here <path> is the complete path of the file or subdirectory to be removed from the branch. See filemodify above for a detailed description of <path>.
Recursively copies an existing file or subdirectory to a different location within the branch. The existing file or directory must exist. If the destination exists it will be completely replaced by the content copied from the source.
'C' SP <path> SP <path> LF
here the first <path> is the source location and the second <path> is the destination. See filemodify above for a detailed description of what <path> may look like. To use a source path that contains SP the path must be quoted.
A filecopy command takes effect immediately. Once the source location has been copied to the destination any future commands applied to the source location will not impact the destination of the copy.
Renames an existing file or subdirectory to a different location within the branch. The existing file or directory must exist. If the destination exists it will be replaced by the source directory.
'R' SP <path> SP <path> LF
here the first <path> is the source location and the second <path> is the destination. See filemodify above for a detailed description of what <path> may look like. To use a source path that contains SP the path must be quoted.
A filerename command takes effect immediately. Once the source location has been renamed to the destination any future commands applied to the source location will create new files there and not impact the destination of the rename.
Note that a filerename is the same as a filecopy followed by a filedelete of the source location. There is a slight performance advantage to using filerename, but the advantage is so small that it is never worth trying to convert a delete/add pair in source material into a rename for fast-import. This filerename command is provided just to simplify frontends that already have rename information and don't want bother with decomposing it into a filecopy followed by a filedelete.
Included in a commit command to remove all files (and also all directories) from the branch. This command resets the internal branch structure to have no files in it, allowing the frontend to subsequently add all interesting files from scratch.
'deleteall' LF
This command is extremely useful if the frontend does not know (or does not care to know) what files are currently on the branch, and therefore cannot generate the proper filedelete commands to update the content.
Issuing a filedeleteall followed by the needed filemodify commands to set the correct content will produce the same results as sending only the needed filemodify and filedelete commands. The filedeleteall approach may however require fast-import to use slightly more memory per active branch (less than 1 MiB for even most large projects); so frontends that can easily obtain only the affected paths for a commit are encouraged to do so.
Included in a commit <notes-ref> command to add a new note annotating a <commit-ish> or change this annotation contents. Internally it is similar to filemodify 100644 on <commit-ish> path (maybe split into subdirectories). It's not advised to use any other commands to write to the <notes-ref> tree except filedeleteall to delete all existing notes in this tree. This command has two different means of specifying the content of the note.
The data content for the note was already supplied by a prior blob command. The frontend just needs to connect it to the commit that is to be annotated.
'N' SP <dataref> SP <commit-ish> LF
Here <dataref> can be either a mark reference (:<idnum>) set by a prior blob command, or a full 40-byte SHA-1 of an existing Git blob object.
The data content for the note has not been supplied yet. The frontend wants to supply it as part of this modify command.
'N' SP 'inline' SP <commit-ish> LF
dataSee below for a detailed description of the data command.
In both formats <commit-ish> is any of the commit specification expressions also accepted by from (see above).
Arranges for fast-import to save a reference to the current object, allowing the frontend to recall this object at a future point in time, without knowing its SHA-1. Here the current object is the object creation command the mark command appears within. This can be commit, tag, and blob, but commit is the most common usage.
'mark' SP ':' <idnum> LF
where <idnum> is the number assigned by the frontend to this mark. The value of <idnum> is expressed as an ASCII decimal integer. The value 0 is reserved and cannot be used as a mark. Only values greater than or equal to 1 may be used as marks.
New marks are created automatically. Existing marks can be moved to another object simply by reusing the same <idnum> in another mark command.
Provides the name of the object in the original source control system. fast-import will simply ignore this directive, but filter processes which operate on and modify the stream before feeding to fast-import may have uses for this information
'original-oid' SP <object-identifier> LF
where <object-identifier> is any string not containing LF.
Creates an annotated tag referring to a specific commit. To create lightweight (non-annotated) tags see the reset command below.
'tag' SP <name> LF
mark?
'from' SP <commit-ish> LF
original-oid?
'tagger' (SP <name>)? SP LT <email> GT SP <when> LF
datawhere <name> is the name of the tag to create.
Tag names are automatically prefixed with refs/tags/ when stored in Git, so importing the CVS branch symbol RELENG-1_0-FINAL would use just RELENG-1_0-FINAL for <name>, and fast-import will write the corresponding ref as refs/tags/RELENG-1_0-FINAL.
The value of <name> must be a valid refname in Git and therefore may contain forward slashes. As LF is not valid in a Git refname, no quoting or escaping syntax is supported here.
The from command is the same as in the commit command; see above for details.
The tagger command uses the same format as committer within commit; again see above for details.
The data command following tagger must supply the annotated tag message (see below for data command syntax). To import an empty tag message use a 0 length data. Tag messages are free-form and are not interpreted by Git. Currently they must be encoded in UTF-8, as fast-import does not permit other encodings to be specified.
Signing annotated tags during import from within fast-import is not supported. Trying to include your own PGP/GPG signature is not recommended, as the frontend does not (easily) have access to the complete set of bytes which normally goes into such a signature. If signing is required, create lightweight tags from within fast-import with reset, then create the annotated versions of those tags offline with the standard git tag process.
Creates (or recreates) the named branch, optionally starting from a specific revision. The reset command allows a frontend to issue a new from command for an existing branch, or to create a new branch from an existing commit without creating a new commit.
'reset' SP <ref> LF
('from' SP <commit-ish> LF)?
LF?For a detailed description of <ref> and <commit-ish> see above under commit and from.
The LF after the command is optional (it used to be required).
The reset command can also be used to create lightweight (non-annotated) tags. For example:
reset refs/tags/938 from :938
would create the lightweight tag refs/tags/938 referring to whatever commit mark :938 references.
Requests writing one file revision to the packfile. The revision is not connected to any commit; this connection must be formed in a subsequent commit command by referencing the blob through an assigned mark.
'blob' LF
mark?
original-oid?
dataThe mark command is optional here as some frontends have chosen to generate the Git SHA-1 for the blob on their own, and feed that directly to commit. This is typically more work than it's worth however, as marks are inexpensive to store and easy to use.
Supplies raw data (for use as blob/file content, commit messages, or annotated tag messages) to fast-import. Data can be supplied using an exact byte count or delimited with a terminating line. Real frontends intended for production-quality conversions should always use the exact byte count format, as it is more robust and performs better. The delimited format is intended primarily for testing fast-import.
Comment lines appearing within the <raw> part of data commands are always taken to be part of the body of the data and are therefore never ignored by fast-import. This makes it safe to import any file/message content whose lines might start with #.
The frontend must specify the number of bytes of data.
'data' SP <count> LF
<raw> LF?where <count> is the exact number of bytes appearing within <raw>. The value of <count> is expressed as an ASCII decimal integer. The LF on either side of <raw> is not included in <count> and will not be included in the imported data.
The LF after <raw> is optional (it used to be required) but recommended. Always including it makes debugging a fast-import stream easier as the next command always starts in column 0 of the next line, even if <raw> did not end with an LF.
A delimiter string is used to mark the end of the data. fast-import will compute the length by searching for the delimiter. This format is primarily useful for testing and is not recommended for real data.
'data' SP '<<' <delim> LF
<raw> LF
<delim> LF
LF?where <delim> is the chosen delimiter string. The string <delim> must not appear on a line by itself within <raw>, as otherwise fast-import will think the data ends earlier than it really does. The LF immediately trailing <raw> is part of <raw>. This is one of the limitations of the delimited format, it is impossible to supply a data chunk which does not have an LF as its last byte.
The LF after <delim> LF is optional (it used to be required).
Record that a mark refers to a given object without first creating any new object.
'alias' LF
mark
'to' SP <commit-ish> LF
LF?For a detailed description of <commit-ish> see above under from.
Forces fast-import to close the current packfile, start a new one, and to save out all current branch refs, tags and marks.
'checkpoint' LF
LF?Note that fast-import automatically switches packfiles when the current packfile reaches --max-pack-size, or 4 GiB, whichever limit is smaller. During an automatic packfile switch fast-import does not update the branch refs, tags or marks.
As a checkpoint can require a significant amount of CPU time and disk IO (to compute the overall pack SHA-1 checksum, generate the corresponding index file, and update the refs) it can easily take several minutes for a single checkpoint command to complete.
Frontends may choose to issue checkpoints during extremely large and long running imports, or when they need to allow another Git process access to a branch. However given that a 30 GiB Subversion repository can be loaded into Git through fast-import in about 3 hours, explicit checkpointing may not be necessary.
The LF after the command is optional (it used to be required).
Causes fast-import to print the entire progress line unmodified to its standard output channel (file descriptor 1) when the command is processed from the input stream. The command otherwise has no impact on the current import, or on any of fast-import's internal state.
'progress' SP <any> LF
LF?The <any> part of the command may contain any sequence of bytes that does not contain LF. The LF after the command is optional. Callers may wish to process the output through a tool such as sed to remove the leading part of the line, for example:
frontend | git fast-import | sed 's/^progress //'
Placing a progress command immediately after a checkpoint will inform the reader when the checkpoint has been completed and it can safely access the refs that fast-import updated.
Causes fast-import to print the SHA-1 corresponding to a mark to stdout or to the file descriptor previously arranged with the --cat-blob-fd argument. The command otherwise has no impact on the current import; its purpose is to retrieve SHA-1s that later commits might want to refer to in their commit messages.
'get-mark' SP ':' <idnum> LF
See Responses To Commands below for details about how to read this output safely.
Causes fast-import to print a blob to a file descriptor previously arranged with the --cat-blob-fd argument. The command otherwise has no impact on the current import; its main purpose is to retrieve blobs that may be in fast-import's memory but not accessible from the target repository.
'cat-blob' SP <dataref> LF
The <dataref> can be either a mark reference (:<idnum>) set previously or a full 40-byte SHA-1 of a Git blob, preexisting or ready to be written.
Output uses the same format as git cat-file --batch:
<sha1> SP 'blob' SP <size> LF <contents> LF
This command can be used where a filemodify directive can appear, allowing it to be used in the middle of a commit. For a filemodify using an inline directive, it can also appear right before the data directive.
See Responses To Commands below for details about how to read this output safely.
Prints information about the object at a path to a file descriptor previously arranged with the --cat-blob-fd argument. This allows printing a blob from the active commit (with cat-blob) or copying a blob or tree from a previous commit for use in the current one (with filemodify).
The ls command can also be used where a filemodify directive can appear, allowing it to be used in the middle of a commit.
This form can only be used in the middle of a commit. The path names a directory entry within fast-import's active commit. The path must be quoted in this case.
'ls' SP <path> LF
The <dataref> can be a mark reference (:<idnum>) or the full 40-byte SHA-1 of a Git tag, commit, or tree object, preexisting or waiting to be written. The path is relative to the top level of the tree named by <dataref>.
'ls' SP <dataref> SP <path> LF
See filemodify above for a detailed description of <path>.
Output uses the same format as git ls-tree <tree> -- <path>:
<mode> SP ('blob' | 'tree' | 'commit') SP <dataref> HT <path> LFThe <dataref> represents the blob, tree, or commit object at <path> and can be used in later get-mark, cat-blob, filemodify, or ls commands.
If there is no file or subtree at that path, git fast-import will instead report
missing SP <path> LF
See Responses To Commands below for details about how to read this output safely.
Require that fast-import supports the specified feature, or abort if it does not.
'feature' SP <feature> ('=' <argument>)? LFThe <feature> part of the command may be any one of the following:
Processes the specified option so that git fast-import behaves in a way that suits the frontend's needs. Note that options specified by the frontend are overridden by any options the user may specify to git fast-import itself.
'option' SP <option> LF
The <option> part of the command may contain any of the options listed in the OPTIONS section that do not change import semantics, without the leading -- and is treated in the same way.
Option commands must be the first commands on the input (not counting feature commands), to give an option command after any non-option command is an error.
The following command-line options change import semantics and may therefore not be passed as option:
New objects written by fast-import are not available immediately. Most fast-import commands have no visible effect until the next checkpoint (or completion). The frontend can send commands to fill fast-import's input pipe without worrying about how quickly they will take effect, which improves performance by simplifying scheduling.
For some frontends, though, it is useful to be able to read back data from the current repository as it is being updated (for example when the source material describes objects in terms of patches to be applied to previously imported objects). This can be accomplished by connecting the frontend and fast-import via bidirectional pipes:
mkfifo fast-import-output frontend <fast-import-output | git fast-import >fast-import-output
A frontend set up this way can use progress, get-mark, ls, and cat-blob commands to read information from the import in progress.
To avoid deadlock, such frontends must completely consume any pending output from progress, ls, get-mark, and cat-blob before performing writes to fast-import that might block.
If fast-import is supplied invalid input it will terminate with a non-zero exit status and create a crash report in the top level of the Git repository it was importing into. Crash reports contain a snapshot of the internal fast-import state as well as the most recent commands that lead up to the crash.
All recent commands (including stream comments, file changes and progress commands) are shown in the command history within the crash report, but raw file data and commit messages are excluded from the crash report. This exclusion saves space within the report file and reduces the amount of buffering that fast-import must perform during execution.
After writing a crash report fast-import will close the current packfile and export the marks table. This allows the frontend developer to inspect the repository state and resume the import from the point where it crashed. The modified branches and tags are not updated during a crash, as the import did not complete successfully. Branch and tag information can be found in the crash report and must be applied manually if the update is needed.
An example crash:
$ cat >in <<END_OF_INPUT # my very first test commit commit refs/heads/master committer Shawn O. Pearce <spearce> 19283 -0400 # who is that guy anyway? data <<EOF this is my commit EOF M 644 inline .gitignore data <<EOF .gitignore EOF M 777 inline bob END_OF_INPUT
$ git fast-import <in fatal: Corrupt mode: M 777 inline bob fast-import: dumping crash report to .git/fast_import_crash_8434
$ cat .git/fast_import_crash_8434
fast-import crash report:
fast-import process: 8434
parent process : 1391
at Sat Sep 1 00:58:12 2007fatal: Corrupt mode: M 777 inline bob
Most Recent Commands Before Crash --------------------------------- # my very first test commit commit refs/heads/master committer Shawn O. Pearce <spearce> 19283 -0400 # who is that guy anyway? data <<EOF M 644 inline .gitignore data <<EOF * M 777 inline bob
Active Branch LRU
-----------------
active_branches = 1 cur, 5 maxpos clock name ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1) 0 refs/heads/master
Inactive Branches ----------------- refs/heads/master: status : active loaded dirty tip commit : 0000000000000000000000000000000000000000 old tree : 0000000000000000000000000000000000000000 cur tree : 0000000000000000000000000000000000000000 commit clock: 0 last pack :
------------------- END OF CRASH REPORT
The following tips and tricks have been collected from various users of fast-import, and are offered here as suggestions.
When doing a repository conversion, use a unique mark per commit (mark :<n>) and supply the --export-marks option on the command line. fast-import will dump a file which lists every mark and the Git object SHA-1 that corresponds to it. If the frontend can tie the marks back to the source repository, it is easy to verify the accuracy and completeness of the import by comparing each Git commit to the corresponding source revision.
Coming from a system such as Perforce or Subversion, this should be quite simple, as the fast-import mark can also be the Perforce changeset number or the Subversion revision number.
Don't bother trying to optimize the frontend to stick to one branch at a time during an import. Although doing so might be slightly faster for fast-import, it tends to increase the complexity of the frontend code considerably.
The branch LRU builtin to fast-import tends to behave very well, and the cost of activating an inactive branch is so low that bouncing around between branches has virtually no impact on import performance.
When importing a renamed file or directory, simply delete the old name(s) and modify the new name(s) during the corresponding commit. Git performs rename detection after-the-fact, rather than explicitly during a commit.
Some other SCM systems let the user create a tag from multiple files which are not from the same commit/changeset. Or to create tags which are a subset of the files available in the repository.
Importing these tags as-is in Git is impossible without making at least one commit which fixes up the files to match the content of the tag. Use fast-import's reset command to reset a dummy branch outside of your normal branch space to the base commit for the tag, then commit one or more file fixup commits, and finally tag the dummy branch.
For example since all normal branches are stored under refs/heads/ name the tag fixup branch TAG_FIXUP. This way it is impossible for the fixup branch used by the importer to have namespace conflicts with real branches imported from the source (the name TAG_FIXUP is not refs/heads/TAG_FIXUP).
When committing fixups, consider using merge to connect the commit(s) which are supplying file revisions to the fixup branch. Doing so will allow tools such as git blame to track through the real commit history and properly annotate the source files.
After fast-import terminates the frontend will need to do rm .git/TAG_FIXUP to remove the dummy branch.
As soon as fast-import completes the Git repository is completely valid and ready for use. Typically this takes only a very short time, even for considerably large projects (100,000+ commits).
However repacking the repository is necessary to improve data locality and access performance. It can also take hours on extremely large projects (especially if -f and a large --window parameter is used). Since repacking is safe to run alongside readers and writers, run the repack in the background and let it finish when it finishes. There is no reason to wait to explore your new Git project!
If you choose to wait for the repack, don't try to run benchmarks or performance tests until repacking is completed. fast-import outputs suboptimal packfiles that are simply never seen in real use situations.
If you are repacking very old imported data (e.g. older than the last year), consider expending some extra CPU time and supplying --window=50 (or higher) when you run git repack. This will take longer, but will also produce a smaller packfile. You only need to expend the effort once, and everyone using your project will benefit from the smaller repository.
Every once in a while have your frontend emit a progress message to fast-import. The contents of the messages are entirely free-form, so one suggestion would be to output the current month and year each time the current commit date moves into the next month. Your users will feel better knowing how much of the data stream has been processed.
When packing a blob fast-import always attempts to deltify against the last blob written. Unless specifically arranged for by the frontend, this will probably not be a prior version of the same file, so the generated delta will not be the smallest possible. The resulting packfile will be compressed, but will not be optimal.
Frontends which have efficient access to all revisions of a single file (for example reading an RCS/CVS ,v file) can choose to supply all revisions of that file as a sequence of consecutive blob commands. This allows fast-import to deltify the different file revisions against each other, saving space in the final packfile. Marks can be used to later identify individual file revisions during a sequence of commit commands.
The packfile(s) created by fast-import do not encourage good disk access patterns. This is caused by fast-import writing the data in the order it is received on standard input, while Git typically organizes data within packfiles to make the most recent (current tip) data appear before historical data. Git also clusters commits together, speeding up revision traversal through better cache locality.
For this reason it is strongly recommended that users repack the repository with git repack -a -d after fast-import completes, allowing Git to reorganize the packfiles for faster data access. If blob deltas are suboptimal (see above) then also adding the -f option to force recomputation of all deltas can significantly reduce the final packfile size (30-50% smaller can be quite typical).
Instead of running git repack you can also run git gc --aggressive, which will also optimize other things after an import (e.g. pack loose refs). As noted in the "AGGRESSIVE" section in the section called “git-gc(1)” the --aggressive option will find new deltas with the -f option to the section called “git-repack(1)”. For the reasons elaborated on above using --aggressive after a fast-import is one of the few cases where it's known to be worthwhile.
There are a number of factors which affect how much memory fast-import requires to perform an import. Like critical sections of core Git, fast-import uses its own memory allocators to amortize any overheads associated with malloc. In practice fast-import tends to amortize any malloc overheads to 0, due to its use of large block allocations.
fast-import maintains an in-memory structure for every object written in this execution. On a 32 bit system the structure is 32 bytes, on a 64 bit system the structure is 40 bytes (due to the larger pointer sizes). Objects in the table are not deallocated until fast-import terminates. Importing 2 million objects on a 32 bit system will require approximately 64 MiB of memory.
The object table is actually a hashtable keyed on the object name (the unique SHA-1). This storage configuration allows fast-import to reuse an existing or already written object and avoid writing duplicates to the output packfile. Duplicate blobs are surprisingly common in an import, typically due to branch merges in the source.
Marks are stored in a sparse array, using 1 pointer (4 bytes or 8 bytes, depending on pointer size) per mark. Although the array is sparse, frontends are still strongly encouraged to use marks between 1 and n, where n is the total number of marks required for this import.
Branches are classified as active and inactive. The memory usage of the two classes is significantly different.
Inactive branches are stored in a structure which uses 96 or 120 bytes (32 bit or 64 bit systems, respectively), plus the length of the branch name (typically under 200 bytes), per branch. fast-import will easily handle as many as 10,000 inactive branches in under 2 MiB of memory.
Active branches have the same overhead as inactive branches, but also contain copies of every tree that has been recently modified on that branch. If subtree include has not been modified since the branch became active, its contents will not be loaded into memory, but if subtree src has been modified by a commit since the branch became active, then its contents will be loaded in memory.
As active branches store metadata about the files contained on that branch, their in-memory storage size can grow to a considerable size (see below).
fast-import automatically moves active branches to inactive status based on a simple least-recently-used algorithm. The LRU chain is updated on each commit command. The maximum number of active branches can be increased or decreased on the command line with --active-branches=.
Trees (aka directories) use just 12 bytes of memory on top of the memory required for their entries (see per active file below). The cost of a tree is virtually 0, as its overhead amortizes out over the individual file entries.
Files (and pointers to subtrees) within active trees require 52 or 64 bytes (32/64 bit platforms) per entry. To conserve space, file and tree names are pooled in a common string table, allowing the filename Makefile to use just 16 bytes (after including the string header overhead) no matter how many times it occurs within the project.
The active branch LRU, when coupled with the filename string pool and lazy loading of subtrees, allows fast-import to efficiently import projects with 2,000+ branches and 45,114+ files in a very limited memory footprint (less than 2.7 MiB per active branch).
Sending SIGUSR1 to the git fast-import process ends the current packfile early, simulating a checkpoint command. The impatient operator can use this facility to peek at the objects and refs from an import in progress, at the cost of some added running time and worse compression.
Everything below this line in this section is selectively included from the the section called “git-config(1)” documentation. The content is the same as what's found there:
Part of the the section called “git(1)” suite
git fetch-pack [--all] [--quiet|-q] [--keep|-k] [--thin] [--include-tag]
[--upload-pack=<git-upload-pack>]
[--depth=<n>] [--no-progress]
[-v] <repository> [<refs>…]
Usually you would want to use git fetch, which is a higher level wrapper of this command, instead.
Invokes git-upload-pack on a possibly remote repository and asks it to send objects missing from this repository, to update the named heads. The list of commits available locally is found out by scanning the local refs/ hierarchy and sent to git-upload-pack running on the other end.
This command degenerates to download everything to complete the asked refs from the remote side when the local side does not have a common ancestor commit.
Take the list of refs from stdin, one per line. If there are refs specified on the command line in addition to this option, then the refs from stdin are processed after those on the command line.
If --stateless-rpc is specified together with this option then the list of refs must be in packet format (pkt-line). Each ref must be in a separate packet, and the list must end with a flush packet.
The remote heads to update from. This is relative to $GIT_DIR (e.g. "HEAD", "refs/heads/master"). When unspecified, update from all heads the remote side has.
If the remote has enabled the options uploadpack.allowTipSHA1InWant, uploadpack.allowReachableSHA1InWant, or uploadpack.allowAnySHA1InWant, they may alternatively be 40-hex sha1s present on the remote.
Part of the the section called “git(1)” suite
git fetch [<options>] [<repository> [<refspec>…]]
git fetch [<options>] <group>
git fetch --multiple [<options>] [(<repository> | <group>)…]
git fetch --all [<options>]
Fetch branches and/or tags (collectively, "refs") from one or more other repositories, along with the objects necessary to complete their histories. Remote-tracking branches are updated (see the description of <refspec> below for ways to control this behavior).
By default, any tag that points into the histories being fetched is also fetched; the effect is to fetch tags that point at branches that you are interested in. This default behavior can be changed by using the --tags or --no-tags options or by configuring remote.<name>.tagOpt. By using a refspec that fetches tags explicitly, you can fetch tags that do not point into branches you are interested in as well.
git fetch can fetch from either a single named repository or URL, or from several repositories at once if <group> is given and there is a remotes.<group> entry in the configuration file. (See the section called “git-config(1)”).
When no remote is specified, by default the origin remote will be used, unless there's an upstream branch configured for the current branch.
The names of refs that are fetched, together with the object names they point at, are written to .git/FETCH_HEAD. This information may be used by scripts or other git commands, such as the section called “git-pull(1)”.
If the source repository is complete, convert a shallow repository to a complete one, removing all the limitations imposed by shallow repositories.
If the source repository is shallow, fetch as much as possible so that the current repository has the same history as the source repository.
By default, Git will report, to the server, commits reachable from all local refs to find common commits in an attempt to reduce the size of the to-be-received packfile. If specified, Git will only report commits reachable from the given tips. This is useful to speed up fetches when the user knows which local ref is likely to have commits in common with the upstream ref being fetched.
This option may be specified more than once; if so, Git will report commits reachable from any of the given commits.
The argument to this option may be a glob on ref names, a ref, or the (possibly abbreviated) SHA-1 of a commit. Specifying a glob is equivalent to specifying this option multiple times, one for each matching ref name.
See also the fetch.negotiationAlgorithm and push.negotiate configuration variables documented in the section called “git-config(1)”, and the --negotiate-only option below.
Do not fetch anything from the server, and instead print the ancestors of the provided --negotiation-tip=* arguments, which we have in common with the server.
This is incompatible with --recurse-submodules=[yes|on-demand]. Internally this is used to implement the push.negotiate option, see the section called “git-config(1)”.
Print the output to standard output in an easy-to-parse format for scripts. See section OUTPUT in the section called “git-fetch(1)” for details.
This is incompatible with --recurse-submodules=[yes|on-demand] and takes precedence over the fetch.output config option.
Before fetching, remove any remote-tracking references that no longer exist on the remote. Tags are not subject to pruning if they are fetched only because of the default tag auto-following or due to a --tags option. However, if tags are fetched due to an explicit refspec (either on the command line or in the remote configuration, for example if the remote was cloned with the --mirror option), then they are also subject to pruning. Supplying --prune-tags is a shorthand for providing the tag refspec.
See the PRUNING section below for more details.
Before fetching, remove any local tags that no longer exist on the remote if --prune is enabled. This option should be used more carefully, unlike --prune it will remove any local references (local tags) that have been created. This option is a shorthand for providing the explicit tag refspec along with --prune, see the discussion about that in its documentation.
See the PRUNING section below for more details.
This option controls if and under what conditions new commits of submodules should be fetched too. When recursing through submodules, git fetch always attempts to fetch "changed" submodules, that is, a submodule that has commits that are referenced by a newly fetched superproject commit but are missing in the local submodule clone. A changed submodule can be fetched as long as it is present locally e.g. in $GIT_DIR/modules/ (see the section called “gitsubmodules(7)”); if the upstream adds a new submodule, that submodule cannot be fetched until it is cloned e.g. by git submodule update.
When set to on-demand, only changed submodules are fetched. When set to yes, all populated submodules are fetched and submodules that are both unpopulated and changed are fetched. When set to no, submodules are never fetched.
When unspecified, this uses the value of fetch.recurseSubmodules if it is set (see the section called “git-config(1)”), defaulting to on-demand if unset. When this option is used without any value, it defaults to yes.
Number of parallel children to be used for all forms of fetching.
If the --multiple option was specified, the different remotes will be fetched in parallel. If multiple submodules are fetched, they will be fetched in parallel. To control them independently, use the config settings fetch.parallel and submodule.fetchJobs (see the section called “git-config(1)”).
Typically, parallel recursive and multi-remote fetches will be faster. By default fetches are performed sequentially, not in parallel.
Specifies which refs to fetch and which local refs to update. When no <refspec>s appear on the command line, the refs to fetch are read from remote.<repository>.fetch variables instead (see CONFIGURED REMOTE-TRACKING BRANCHES below).
The format of a <refspec> parameter is an optional plus +, followed by the source <src>, followed by a colon :, followed by the destination <dst>. The colon can be omitted when <dst> is empty. <src> is typically a ref, or a glob pattern with a single * that is used to match a set of refs, but it can also be a fully spelled hex object name.
A <refspec> may contain a * in its <src> to indicate a simple pattern match. Such a refspec functions like a glob that matches any ref with the pattern. A pattern <refspec> must have one and only one * in both the <src> and <dst>. It will map refs to the destination by replacing the * with the contents matched from the source.
If a refspec is prefixed by ^, it will be interpreted as a negative refspec. Rather than specifying which refs to fetch or which local refs to update, such a refspec will instead specify refs to exclude. A ref will be considered to match if it matches at least one positive refspec, and does not match any negative refspec. Negative refspecs can be useful to restrict the scope of a pattern refspec so that it will not include specific refs. Negative refspecs can themselves be pattern refspecs. However, they may only contain a <src> and do not specify a <dst>. Fully spelled out hex object names are also not supported.
tag <tag> means the same as refs/tags/<tag>:refs/tags/<tag>; it requests fetching everything up to the given tag.
The remote ref that matches <src> is fetched, and if <dst> is not an empty string, an attempt is made to update the local ref that matches it.
Whether that update is allowed without --force depends on the ref namespace it's being fetched to, the type of object being fetched, and whether the update is considered to be a fast-forward. Generally, the same rules apply for fetching as when pushing, see the <refspec>... section of the section called “git-push(1)” for what those are. Exceptions to those rules particular to git fetch are noted below.
Until Git version 2.20, and unlike when pushing with the section called “git-push(1)”, any updates to refs/tags/* would be accepted without + in the refspec (or --force). When fetching, we promiscuously considered all tag updates from a remote to be forced fetches. Since Git version 2.20, fetching to update refs/tags/* works the same way as when pushing. I.e. any updates will be rejected without + in the refspec (or --force).
Unlike when pushing with the section called “git-push(1)”, any updates outside of refs/{tags,heads}/* will be accepted without + in the refspec (or --force), whether that's swapping e.g. a tree object for a blob, or a commit for another commit that doesn't have the previous commit as an ancestor etc.
Unlike when pushing with the section called “git-push(1)”, there is no configuration which'll amend these rules, and nothing like a pre-fetch hook analogous to the pre-receive hook.
As with pushing with the section called “git-push(1)”, all of the rules described above about what's not allowed as an update can be overridden by adding an optional leading + to a refspec (or using the --force command line option). The only exception to this is that no amount of forcing will make the refs/heads/* namespace accept a non-commit object.
When the remote branch you want to fetch is known to be rewound and rebased regularly, it is expected that its new tip will not be a descendant of its previous tip (as stored in your remote-tracking branch the last time you fetched). You would want to use the + sign to indicate non-fast-forward updates will be needed for such branches. There is no way to determine or declare that a branch will be made available in a repository with this behavior; the pulling user simply must know this is the expected usage pattern for a branch.
In general, URLs contain information about the transport protocol, the address of the remote server, and the path to the repository. Depending on the transport protocol, some of this information may be absent.
Git supports ssh, git, http, and https protocols (in addition, ftp and ftps can be used for fetching, but this is inefficient and deprecated; do not use them).
The native transport (i.e. git:// URL) does no authentication and should be used with caution on unsecured networks.
The following syntaxes may be used with them:
An alternative scp-like syntax may also be used with the ssh protocol:
This syntax is only recognized if there are no slashes before the first colon. This helps differentiate a local path that contains a colon. For example the local path foo:bar could be specified as an absolute path or ./foo:bar to avoid being misinterpreted as an ssh url.
The ssh and git protocols additionally support ~<username> expansion:
For local repositories, also supported by Git natively, the following syntaxes may be used:
These two syntaxes are mostly equivalent, except when cloning, when the former implies --local option. See the section called “git-clone(1)” for details.
git clone, git fetch and git pull, but not git push, will also accept a suitable bundle file. See the section called “git-bundle(1)”.
When Git doesn't know how to handle a certain transport protocol, it attempts to use the remote-<transport> remote helper, if one exists. To explicitly request a remote helper, the following syntax may be used:
where <address> may be a path, a server and path, or an arbitrary URL-like string recognized by the specific remote helper being invoked. See the section called “gitremote-helpers(7)” for details.
If there are a large number of similarly-named remote repositories and you want to use a different format for them (such that the URLs you use will be rewritten into URLs that work), you can create a configuration section of the form:
[url "<actual-url-base>"]
insteadOf = <other-url-base>
For example, with this:
[url "git://git.host.xz/"]
insteadOf = host.xz:/path/to/
insteadOf = work:a URL like "work:repo.git" or like "host.xz:/path/to/repo.git" will be rewritten in any context that takes a URL to be "git://git.host.xz/repo.git".
If you want to rewrite URLs for push only, you can create a configuration section of the form:
[url "<actual-url-base>"]
pushInsteadOf = <other-url-base>
For example, with this:
[url "ssh://example.org/"]
pushInsteadOf = git://example.org/a URL like "git://example.org/path/to/repo.git" will be rewritten to "ssh://example.org/path/to/repo.git" for pushes, but pulls will still use the original URL.
The name of one of the following can be used instead of a URL as <repository> argument:
All of these also allow you to omit the refspec from the command line because they each contain a refspec which git will use by default.
You can choose to provide the name of a remote which you had previously configured using the section called “git-remote(1)”, the section called “git-config(1)” or even by a manual edit to the $GIT_DIR/config file. The URL of this remote will be used to access the repository. The refspec of this remote will be used by default when you do not provide a refspec on the command line. The entry in the config file would appear like this:
[remote "<name>"]
url = <URL>
pushurl = <pushurl>
push = <refspec>
fetch = <refspec>The <pushurl> is used for pushes only. It is optional and defaults to <URL>. Pushing to a remote affects all defined pushurls or all defined urls if no pushurls are defined. Fetch, however, will only fetch from the first defined url if multiple urls are defined.
You can choose to provide the name of a file in $GIT_DIR/remotes. The URL in this file will be used to access the repository. The refspec in this file will be used as default when you do not provide a refspec on the command line. This file should have the following format:
URL: one of the above URL formats
Push: <refspec>
Pull: <refspec>Push: lines are used by git push and Pull: lines are used by git pull and git fetch. Multiple Push: and Pull: lines may be specified for additional branch mappings.
You can choose to provide the name of a file in $GIT_DIR/branches. The URL in this file will be used to access the repository. This file should have the following format:
<URL>#<head>
<URL> is required; #<head> is optional.
Depending on the operation, git will use one of the following refspecs, if you don't provide one on the command line. <branch> is the name of this file in $GIT_DIR/branches and <head> defaults to master.
git fetch uses:
refs/heads/<head>:refs/heads/<branch>
git push uses:
HEAD:refs/heads/<head>
You often interact with the same remote repository by regularly and repeatedly fetching from it. In order to keep track of the progress of such a remote repository, git fetch allows you to configure remote.<repository>.fetch configuration variables.
Typically such a variable may look like this:
[remote "origin"]
fetch = +refs/heads/*:refs/remotes/origin/*This configuration is used in two ways:
The latter use of the remote.<repository>.fetch values can be overridden by giving the --refmap=<refspec> parameter(s) on the command line.
Git has a default disposition of keeping data unless it's explicitly thrown away; this extends to holding onto local references to branches on remotes that have themselves deleted those branches.
If left to accumulate, these stale references might make performance worse on big and busy repos that have a lot of branch churn, and e.g. make the output of commands like git branch -a --contains <commit> needlessly verbose, as well as impacting anything else that'll work with the complete set of known references.
These remote-tracking references can be deleted as a one-off with either of:
# While fetching $ git fetch --prune <name> # Only prune, don't fetch $ git remote prune <name>
To prune references as part of your normal workflow without needing to remember to run that, set fetch.prune globally, or remote.<name>.prune per-remote in the config. See the section called “git-config(1)”.
Here's where things get tricky and more specific. The pruning feature doesn't actually care about branches, instead it'll prune local ←→ remote-references as a function of the refspec of the remote (see <refspec> and CONFIGURED REMOTE-TRACKING BRANCHES above).
Therefore if the refspec for the remote includes e.g. refs/tags/*:refs/tags/*, or you manually run e.g. git fetch --prune <name> "refs/tags/*:refs/tags/*" it won't be stale remote tracking branches that are deleted, but any local tag that doesn't exist on the remote.
This might not be what you expect, i.e. you want to prune remote <name>, but also explicitly fetch tags from it, so when you fetch from it you delete all your local tags, most of which may not have come from the <name> remote in the first place.
So be careful when using this with a refspec like refs/tags/*:refs/tags/*, or any other refspec which might map references from multiple remotes to the same local namespace.
Since keeping up-to-date with both branches and tags on the remote is a common use-case the --prune-tags option can be supplied along with --prune to prune local tags that don't exist on the remote, and force-update those tags that differ. Tag pruning can also be enabled with fetch.pruneTags or remote.<name>.pruneTags in the config. See the section called “git-config(1)”.
The --prune-tags option is equivalent to having refs/tags/*:refs/tags/* declared in the refspecs of the remote. This can lead to some seemingly strange interactions:
# These both fetch tags $ git fetch --no-tags origin 'refs/tags/*:refs/tags/*' $ git fetch --no-tags --prune-tags origin
The reason it doesn't error out when provided without --prune or its config versions is for flexibility of the configured versions, and to maintain a 1=1 mapping between what the command line flags do, and what the configuration versions do.
It's reasonable to e.g. configure fetch.pruneTags=true in ~/.gitconfig to have tags pruned whenever git fetch --prune is run, without making every invocation of git fetch without --prune an error.
Pruning tags with --prune-tags also works when fetching a URL instead of a named remote. These will all prune tags not found on origin:
$ git fetch origin --prune --prune-tags $ git fetch origin --prune 'refs/tags/*:refs/tags/*' $ git fetch <url-of-origin> --prune --prune-tags $ git fetch <url-of-origin> --prune 'refs/tags/*:refs/tags/*'
The output of "git fetch" depends on the transport method used; this section describes the output when fetching over the Git protocol (either locally or via ssh) and Smart HTTP protocol.
The status of the fetch is output in tabular form, with each line representing the status of a single ref. Each line is of the form:
<flag> <summary> <from> -> <to> [<reason>]
When using --porcelain, the output format is intended to be machine-parseable. In contrast to the human-readable output formats it thus prints to standard output instead of standard error. Each line is of the form:
<flag> <old-object-id> <new-object-id> <local-reference>
The status of up-to-date refs is shown only if the --verbose option is used.
In compact output mode, specified with configuration variable fetch.output, if either entire <from> or <to> is found in the other string, it will be substituted with * in the other string. For example, master -> origin/master becomes master -> origin/*.
A single character indicating the status of the ref:
Update the remote-tracking branches:
$ git fetch origin
The above command copies all branches from the remote refs/heads/ namespace and stores them to the local refs/remotes/origin/ namespace, unless the remote.<repository>.fetch option is used to specify a non-default refspec.
Using refspecs explicitly:
$ git fetch origin +seen:seen maint:tmp
This updates (or creates, as necessary) branches seen and tmp in the local repository by fetching from the branches (respectively) seen and maint from the remote repository.
The seen branch will be updated even if it does not fast-forward, because it is prefixed with a plus sign; tmp will not be.
Peek at a remote's branch, without configuring the remote in your local repository:
$ git fetch git://git.kernel.org/pub/scm/git/git.git maint $ git log FETCH_HEAD
The first command fetches the maint branch from the repository at git://git.kernel.org/pub/scm/git/git.git and the second command uses FETCH_HEAD to examine the branch with the section called “git-log(1)”. The fetched objects will eventually be removed by git's built-in housekeeping (see the section called “git-gc(1)”).
The fetch and push protocols are not designed to prevent one side from stealing data from the other repository that was not intended to be shared. If you have private data that you need to protect from a malicious peer, your best option is to store it in another repository. This applies to both clients and servers. In particular, namespaces on a server are not effective for read access control; you should only grant read access to a namespace to clients that you would trust with read access to the entire repository.
The known attack vectors are as follows:
Everything below this line in this section is selectively included from the the section called “git-config(1)” documentation. The content is the same as what's found there:
Control how information about the commits in the local repository is sent when negotiating the contents of the packfile to be sent by the server. Set to "consecutive" to use an algorithm that walks over consecutive commits checking each one. Set to "skipping" to use an algorithm that skips commits in an effort to converge faster, but may result in a larger-than-necessary packfile; or set to "noop" to not send any information at all, which will almost certainly result in a larger-than-necessary packfile, but will skip the negotiation step. Set to "default" to override settings made previously and use the default behaviour. The default is normally "consecutive", but if feature.experimental is true, then the default is "skipping". Unknown values will cause git fetch to error out.
See also the --negotiate-only and --negotiation-tip options to the section called “git-fetch(1)”.
Specifies the maximal number of fetch operations to be run in parallel at a time (submodules, or remotes when the --multiple option of the section called “git-fetch(1)” is in effect).
A value of 0 will give some reasonable default. If unset, it defaults to 1.
For submodules, this setting can be overridden using the submodule.fetchJobs config setting.
This value stores a URI for downloading Git object data from a bundle URI before performing an incremental fetch from the origin Git server. This is similar to how the --bundle-uri option behaves in the section called “git-clone(1)”. git clone --bundle-uri will set the fetch.bundleURI value if the supplied bundle URI contains a bundle list that is organized for incremental fetches.
If you modify this value and your repository has a fetch.bundleCreationToken value, then remove that fetch.bundleCreationToken value before fetching from the new bundle URI.
When using fetch.bundleURI to fetch incrementally from a bundle list that uses the "creationToken" heuristic, this config value stores the maximum creationToken value of the downloaded bundles. This value is used to prevent downloading bundles in the future if the advertised creationToken is not strictly larger than this value.
The creation token values are chosen by the provider serving the specific bundle URI. If you modify the URI at fetch.bundleURI, then be sure to remove the value for the fetch.bundleCreationToken value before fetching.
Using --recurse-submodules can only fetch new commits in submodules that are present locally e.g. in $GIT_DIR/modules/. If the upstream adds a new submodule, that submodule cannot be fetched until it is cloned e.g. by git submodule update. This is expected to be fixed in a future Git version.
Part of the the section called “git(1)” suite
git filter-branch [--setup <command>] [--subdirectory-filter <directory>]
[--env-filter <command>] [--tree-filter <command>]
[--index-filter <command>] [--parent-filter <command>]
[--msg-filter <command>] [--commit-filter <command>]
[--tag-name-filter <command>] [--prune-empty]
[--original <namespace>] [-d <directory>] [-f | --force]
[--state-branch <branch>] [--] [<rev-list-options>…]
git filter-branch has a plethora of pitfalls that can produce non-obvious manglings of the intended history rewrite (and can leave you with little time to investigate such problems since it has such abysmal performance). These safety and performance issues cannot be backward compatibly fixed and as such, its use is not recommended. Please use an alternative history filtering tool such as git filter-repo. If you still need to use git filter-branch, please carefully read the section called “SAFETY” (and the section called “PERFORMANCE”) to learn about the land mines of filter-branch, and then vigilantly avoid as many of the hazards listed there as reasonably possible.
Lets you rewrite Git revision history by rewriting the branches mentioned in the <rev-list-options>, applying custom filters on each revision. Those filters can modify each tree (e.g. removing a file or running a perl rewrite on all files) or information about each commit. Otherwise, all information (including original commit times or merge information) will be preserved.
The command will only rewrite the positive refs mentioned in the command line (e.g. if you pass a..b, only b will be rewritten). If you specify no filters, the commits will be recommitted without any changes, which would normally have no effect. Nevertheless, this may be useful in the future for compensating for some Git bugs or such, therefore such a usage is permitted.
NOTE: This command honors .git/info/grafts file and refs in the refs/replace/ namespace. If you have any grafts or replacement refs defined, running this command will make them permanent.
WARNING! The rewritten history will have different object names for all the objects and will not converge with the original branch. You will not be able to easily push and distribute the rewritten branch on top of the original branch. Please do not use this command if you do not know the full implications, and avoid using it anyway, if a simple single commit would suffice to fix your problem. (See the "RECOVERING FROM UPSTREAM REBASE" section in the section called “git-rebase(1)” for further information about rewriting published history.)
Always verify that the rewritten version is correct: The original refs, if different from the rewritten ones, will be stored in the namespace refs/original/.
Note that since this operation is very I/O expensive, it might be a good idea to redirect the temporary directory off-disk with the -d option, e.g. on tmpfs. Reportedly the speedup is very noticeable.
The filters are applied in the order as listed below. The <command> argument is always evaluated in the shell context using the eval command (with the notable exception of the commit filter, for technical reasons). Prior to that, the $GIT_COMMIT environment variable will be set to contain the id of the commit being rewritten. Also, GIT_AUTHOR_NAME, GIT_AUTHOR_EMAIL, GIT_AUTHOR_DATE, GIT_COMMITTER_NAME, GIT_COMMITTER_EMAIL, and GIT_COMMITTER_DATE are taken from the current commit and exported to the environment, in order to affect the author and committer identities of the replacement commit created by the section called “git-commit-tree(1)” after the filters have run.
If any evaluation of <command> returns a non-zero exit status, the whole operation will be aborted.
A map function is available that takes an "original sha1 id" argument and outputs a "rewritten sha1 id" if the commit has been already rewritten, and "original sha1 id" otherwise; the map function can return several ids on separate lines if your commit filter emitted multiple commits.
This is the filter for performing the commit. If this filter is specified, it will be called instead of the git commit-tree command, with arguments of the form "<TREE_ID> [(-p <PARENT_COMMIT_ID>)…]" and the log message on stdin. The commit id is expected on stdout.
As a special extension, the commit filter may emit multiple commit ids; in that case, the rewritten children of the original commit will have all of them as parents.
You can use the map convenience function in this filter, and other convenience functions, too. For example, calling skip_commit "$@" will leave out the current commit (but not its changes! If you want that, use git rebase instead).
You can also use the git_commit_non_empty_tree "$@" instead of git commit-tree "$@" if you don't wish to keep commits with a single parent and that makes no change to the tree.
This is the filter for rewriting tag names. When passed, it will be called for every tag ref that points to a rewritten object (or to a tag object which points to a rewritten object). The original tag name is passed via standard input, and the new tag name is expected on standard output.
The original tags are not deleted, but can be overwritten; use "--tag-name-filter cat" to simply update the tags. In this case, be very careful and make sure you have the old tags backed up in case the conversion has run afoul.
Nearly proper rewriting of tag objects is supported. If the tag has a message attached, a new tag object will be created with the same message, author, and timestamp. If the tag has a signature attached, the signature will be stripped. It is by definition impossible to preserve signatures. The reason this is "nearly" proper, is because ideally if the tag did not change (points to the same object, has the same name, etc.) it should retain any signature. That is not the case, signatures will always be removed, buyer beware. There is also no support for changing the author or timestamp (or the tag message for that matter). Tags which point to other tags will be rewritten to point to the underlying commit.
By using the section called “git-rev-list(1)” arguments, e.g., path limiters, you can limit the set of revisions which get rewritten. However, positive refs on the command line are distinguished: we don't let them be excluded by such limiters. For this purpose, they are instead rewritten to point at the nearest ancestor that was not excluded.
On success, the exit status is 0. If the filter can't find any commits to rewrite, the exit status is 2. On any other error, the exit status may be any other non-zero value.
Suppose you want to remove a file (containing confidential information or copyright violation) from all commits:
git filter-branch --tree-filter 'rm filename' HEAD
However, if the file is absent from the tree of some commit, a simple rm filename will fail for that tree and commit. Thus you may instead want to use rm -f filename as the script.
Using --index-filter with git rm yields a significantly faster version. Like with using rm filename, git rm --cached filename will fail if the file is absent from the tree of a commit. If you want to "completely forget" a file, it does not matter when it entered history, so we also add --ignore-unmatch:
git filter-branch --index-filter 'git rm --cached --ignore-unmatch filename' HEAD
Now, you will get the rewritten history saved in HEAD.
To rewrite the repository to look as if foodir/ had been its project root, and discard all other history:
git filter-branch --subdirectory-filter foodir -- --all
Thus you can, e.g., turn a library subdirectory into a repository of its own. Note the -- that separates filter-branch options from revision options, and the --all to rewrite all branches and tags.
To set a commit (which typically is at the tip of another history) to be the parent of the current initial commit, in order to paste the other history behind the current history:
git filter-branch --parent-filter 'sed "s/^\$/-p <graft-id>/"' HEAD
(if the parent string is empty - which happens when we are dealing with the initial commit - add graftcommit as a parent). Note that this assumes history with a single root (that is, no merge without common ancestors happened). If this is not the case, use:
git filter-branch --parent-filter \
'test $GIT_COMMIT = <commit-id> && echo "-p <graft-id>" || cat' HEADor even simpler:
git replace --graft $commit-id $graft-id git filter-branch $graft-id..HEAD
To remove commits authored by "Darl McBribe" from the history:
git filter-branch --commit-filter '
if [ "$GIT_AUTHOR_NAME" = "Darl McBribe" ];
then
skip_commit "$@";
else
git commit-tree "$@";
fi' HEADThe function skip_commit is defined as follows:
skip_commit()
{
shift;
while [ -n "$1" ];
do
shift;
map "$1";
shift;
done;
}The shift magic first throws away the tree id and then the -p parameters. Note that this handles merges properly! In case Darl committed a merge between P1 and P2, it will be propagated properly and all children of the merge will become merge commits with P1,P2 as their parents instead of the merge commit.
NOTE the changes introduced by the commits, and which are not reverted by subsequent commits, will still be in the rewritten branch. If you want to throw out changes together with the commits, you should use the interactive mode of git rebase.
You can rewrite the commit log messages using --msg-filter. For example, git svn-id strings in a repository created by git svn can be removed this way:
git filter-branch --msg-filter '
sed -e "/^git-svn-id:/d"
'If you need to add Acked-by lines to, say, the last 10 commits (none of which is a merge), use this command:
git filter-branch --msg-filter '
cat &&
echo "Acked-by: Bugs Bunny <bunny@bugzilla.org>"
' HEAD~10..HEADThe --env-filter option can be used to modify committer and/or author identity. For example, if you found out that your commits have the wrong identity due to a misconfigured user.email, you can make a correction, before publishing the project, like this:
git filter-branch --env-filter '
if test "$GIT_AUTHOR_EMAIL" = "root@localhost"
then
GIT_AUTHOR_EMAIL=john@example.com
fi
if test "$GIT_COMMITTER_EMAIL" = "root@localhost"
then
GIT_COMMITTER_EMAIL=john@example.com
fi
' -- --allTo restrict rewriting to only part of the history, specify a revision range in addition to the new branch name. The new branch name will point to the top-most revision that a git rev-list of this range will print.
Consider this history:
D--E--F--G--H
/ /
A--B-----CTo rewrite only commits D,E,F,G,H, but leave A, B and C alone, use:
git filter-branch ... C..H
To rewrite commits E,F,G,H, use one of these:
git filter-branch ... C..H --not D git filter-branch ... D..H --not C
To move the whole tree into a subdirectory, or remove it from there:
git filter-branch --index-filter \
'git ls-files -s | sed "s-\t\"*-&newsubdir/-" |
GIT_INDEX_FILE=$GIT_INDEX_FILE.new \
git update-index --index-info &&
mv "$GIT_INDEX_FILE.new" "$GIT_INDEX_FILE"' HEADgit-filter-branch can be used to get rid of a subset of files, usually with some combination of --index-filter and --subdirectory-filter. People expect the resulting repository to be smaller than the original, but you need a few more steps to actually make it smaller, because Git tries hard not to lose your objects until you tell it to. First make sure that:
Then there are two ways to get a smaller repository. A safer way is to clone, that keeps your original intact.
If you really don't want to clone it, for whatever reasons, check the following points instead (in this order). This is a very destructive approach, so make a backup or go back to cloning it. You have been warned.
The performance of git-filter-branch is glacially slow; its design makes it impossible for a backward-compatible implementation to ever be fast:
If you try and cheat and try to make git-filter-branch only work on files modified in a commit, then two things happen
git-filter-branch itself is written in shell, which is kind of slow. This is the one performance issue that could be backward-compatibly fixed, but compared to the above problems that are intrinsic to the design of git-filter-branch, the language of the tool itself is a relatively minor issue.
The git filter-repo tool is an alternative to git-filter-branch which does not suffer from these performance problems or the safety problems (mentioned below). For those with existing tooling which relies upon git-filter-branch, git filter-repo also provides filter-lamely, a drop-in git-filter-branch replacement (with a few caveats). While filter-lamely suffers from all the same safety issues as git-filter-branch, it at least ameliorates the performance issues a little.
git-filter-branch is riddled with gotchas resulting in various ways to easily corrupt repos or end up with a mess worse than what you started with:
It's far too easy to accidentally mix up old and new history. It's still possible with any tool, but git-filter-branch almost invites it. If lucky, the only downside is users getting frustrated that they don't know how to shrink their repo and remove the old stuff. If unlucky, they merge old and new history and end up with multiple "copies" of each commit, some of which have unwanted or sensitive files and others which don't. This comes about in multiple different ways:
Annotated tags can be accidentally converted to lightweight tags, due to either of two issues:
Also, the poor performance of git-filter-branch often leads to safety issues:
Part of the the section called “git(1)” suite
git fmt-merge-msg [-m <message>] [--into-name <branch>] [--log[=<n>] | --no-log]
git fmt-merge-msg [-m <message>] [--log[=<n>] | --no-log] -F <file>
Takes the list of merged objects on stdin and produces a suitable commit message to be used for the merge commit, usually to be passed as the <merge-message> argument of git merge.
This command is intended mostly for internal use by scripts automatically invoking git merge.
By adding a glob that matches the names of integration branches to this multi-valued configuration variable, the default merge message computed for merges into these integration branches will omit "into <branch-name>" from its title.
An element with an empty value can be used to clear the list of globs accumulated from previous configuration entries. When there is no merge.suppressDest variable defined, the default value of master is used for backward compatibility.
$ git fetch origin master $ git fmt-merge-msg --log <$GIT_DIR/FETCH_HEAD
Print a log message describing a merge of the "master" branch from the "origin" remote.
Part of the the section called “git(1)” suite
git for-each-ref [--count=<count>] [--shell|--perl|--python|--tcl]
[(--sort=<key>)…] [--format=<format>]
[--include-root-refs] [ --stdin | <pattern>… ]
[--points-at=<object>]
[--merged[=<object>]] [--no-merged[=<object>]]
[--contains[=<object>]] [--no-contains[=<object>]]
[--exclude=<pattern> …]
Iterate over all refs that match <pattern> and show them according to the given <format>, after sorting them according to the given set of <key>. If <count> is given, stop after showing that many refs. The interpolated values in <format> can optionally be quoted as string literals in the specified host language allowing their direct evaluation in that language.
A string that interpolates %(fieldname) from a ref being shown and the object it points at. In addition, the string literal %% renders as % and %xx - where xx are hex digits - renders as the character with hex code xx. For example, %00 interpolates to \0 (NUL), %09 to \t (TAB), and %0a to \n (LF).
When unspecified, <format> defaults to %(objectname) SPC %(objecttype) TAB %(refname).
Various values from structured fields in referenced objects can be used to interpolate into the resulting output, or as sort keys.
For all objects, the following names can be used:
The name of the ref (the part after $GIT_DIR/). For a non-ambiguous short name of the ref append :short. The option core.warnAmbiguousRefs is used to select the strict abbreviation mode. If lstrip=<N> (rstrip=<N>) is appended, strips <N> slash-separated path components from the front (back) of the refname (e.g. %(refname:lstrip=2) turns refs/tags/foo into foo and %(refname:rstrip=2) turns refs/tags/foo into refs). If <N> is a negative number, strip as many path components as necessary from the specified end to leave -<N> path components (e.g. %(refname:lstrip=-2) turns refs/tags/foo into tags/foo and %(refname:rstrip=-1) turns refs/tags/foo into refs). When the ref does not have enough components, the result becomes an empty string if stripping with positive <N>, or it becomes the full refname if stripping with negative <N>. Neither is an error.
strip can be used as a synonym to lstrip.
The name of a local ref which can be considered upstream from the displayed ref. Respects :short, :lstrip and :rstrip in the same way as refname above. Additionally respects :track to show "[ahead N, behind M]" and :trackshort to show the terse version: ">" (ahead), "<" (behind), "<>" (ahead and behind), or "=" (in sync). :track also prints "[gone]" whenever unknown upstream ref is encountered. Append :track,nobracket to show tracking information without brackets (i.e "ahead N, behind M").
For any remote-tracking branch %(upstream), %(upstream:remotename) and %(upstream:remoteref) refer to the name of the remote and the name of the tracked remote ref, respectively. In other words, the remote-tracking branch can be updated explicitly and individually by using the refspec %(upstream:remoteref):%(upstream) to fetch from %(upstream:remotename).
Has no effect if the ref does not have tracking information associated with it. All the options apart from nobracket are mutually exclusive, but if used together the last option is selected.
In at most one row, (<committish>) will appear to indicate the ref that is most likely the ref used as a starting point for the branch that produced <committish>. This choice is made using a heuristic: choose the ref that minimizes the number of commits in the first-parent history of <committish> and not in the first-parent history of the ref.
For example, consider the following figure of first-parent histories of several refs:
*--*--*--*--*--* refs/heads/A
\
\
*--*--*--* refs/heads/B
\ \
\ \
* * refs/heads/C
\
\
*--* refs/heads/DHere, if A, B, and C are the filtered references, and the format string is %(refname):%(is-base:D), then the output would be
refs/heads/A: refs/heads/B:(D) refs/heads/C:
This is because the first-parent history of D has its earliest intersection with the first-parent histories of the filtered refs at a common first-parent ancestor of B and C and ties are broken by the earliest ref in the sorted order.
Note that this token will not appear if the first-parent history of <committish> does not intersect the first-parent histories of the filtered refs.
A human-readable name, like the section called “git-describe(1)”; empty string for undescribable commits. The describe string may be followed by a colon and one or more comma-separated options.
In addition to the above, for commit and tag objects, the header field names (tree, parent, object, type, and tag) can be used to specify the value in the header field. Fields tree and parent can also be used with modifier :short and :short=<length> just like objectname.
For commit and tag objects, the special creatordate and creator fields will correspond to the appropriate date or name-email-date tuple from the committer or tagger fields depending on the object type. These are intended for working on a mix of annotated and lightweight tags.
For tag objects, a fieldname prefixed with an asterisk (*) expands to the fieldname value of the peeled object, rather than that of the tag object itself.
Fields that have name-email-date tuple as its value (author, committer, and tagger) can be suffixed with name, email, and date to extract the named component. For email fields (authoremail, committeremail and taggeremail), :trim can be appended to get the email without angle brackets, and :localpart to get the part before the @ symbol out of the trimmed email. In addition to these, the :mailmap option and the corresponding :mailmap,trim and :mailmap,localpart can be used (order does not matter) to get values of the name and email according to the .mailmap file or according to the file set in the mailmap.file or mailmap.blob configuration variable (see the section called “gitmailmap(5)”).
The raw data in an object is raw.
Note that --format=%(raw) can not be used with --python, --shell, --tcl, because such language may not support arbitrary binary data in their string variable type.
The message in a commit or a tag object is contents, from which contents:<part> can be used to extract various parts out of:
Additionally, the trailers as interpreted by the section called “git-interpret-trailers(1)” are obtained as trailers[:options] (or by using the historical alias contents:trailers[:options]). For valid [:option] values see trailers section of the section called “git-log(1)”.
For sorting purposes, fields with numeric values sort in numeric order (objectsize, authordate, committerdate, creatordate, taggerdate). All other fields are used to sort in their byte-value order.
There is also an option to sort by versions, this can be done by using the fieldname version:refname or its alias v:refname.
In any case, a field name that refers to a field inapplicable to the object referred by the ref does not cause an error. It returns an empty string instead.
As a special case for the date-type fields, you may specify a format for the date by adding : followed by date format name (see the values the --date option to the section called “git-rev-list(1)” takes). If this formatting is provided in a --sort key, references will be sorted according to the byte-value of the formatted string rather than the numeric value of the underlying timestamp.
Some atoms like %(align) and %(if) always require a matching %(end). We call them "opening atoms" and sometimes denote them as %($open).
When a scripting language specific quoting is in effect, everything between a top-level opening atom and its matching %(end) is evaluated according to the semantics of the opening atom and only its result from the top-level is quoted.
An example directly producing formatted text. Show the most recent 3 tagged commits:
#!/bin/sh git for-each-ref --count=3 --sort='-*authordate' \ --format='From: %(*authorname) %(*authoremail) Subject: %(*subject) Date: %(*authordate) Ref: %(*refname) %(*body) ' 'refs/tags'
A simple example showing the use of shell eval on the output, demonstrating the use of --shell. List the prefixes of all heads:
#!/bin/sh
git for-each-ref --shell --format="ref=%(refname)" refs/heads | \
while read entry
do
eval "$entry"
echo `dirname $ref`
doneA bit more elaborate report on tags, demonstrating that the format may be an entire script:
#!/bin/sh
fmt='
r=%(refname)
t=%(*objecttype)
T=${r#refs/tags/}
o=%(*objectname)
n=%(*authorname)
e=%(*authoremail)
s=%(*subject)
d=%(*authordate)
b=%(*body)
kind=Tag
if test "z$t" = z
then
# could be a lightweight tag
t=%(objecttype)
kind="Lightweight tag"
o=%(objectname)
n=%(authorname)
e=%(authoremail)
s=%(subject)
d=%(authordate)
b=%(body)
fi
echo "$kind $T points at a $t object $o"
if test "z$t" = zcommit
then
echo "The commit was authored by $n $e
at $d, and titled
$s
Its message reads as:
"
echo "$b" | sed -e "s/^/ /"
echo
fi
'
eval=`git for-each-ref --shell --format="$fmt" \
--sort='*objecttype' \
--sort=-taggerdate \
refs/tags`
eval "$eval"An example to show the usage of %(if)…%(then)…%(else)…%(end). This prefixes the current branch with a star.
git for-each-ref --format="%(if)%(HEAD)%(then)* %(else) %(end)%(refname:short)" refs/heads/
An example to show the usage of %(if)…%(then)…%(end). This prints the authorname, if present.
git for-each-ref --format="%(refname)%(if)%(authorname)%(then) Authored by: %(authorname)%(end)"
Note that the sizes of objects on disk are reported accurately, but care should be taken in drawing conclusions about which refs or objects are responsible for disk usage. The size of a packed non-delta object may be much larger than the size of objects which delta against it, but the choice of which object is the base and which is the delta is arbitrary and is subject to change during a repack.
Note also that multiple copies of an object may be present in the object database; in this case, it is undefined which copy's size or delta base will be reported.
When combining multiple --contains and --no-contains filters, only references that contain at least one of the --contains commits and contain none of the --no-contains commits are shown.
When combining multiple --merged and --no-merged filters, only references that are reachable from at least one of the --merged commits and from none of the --no-merged commits are shown.
Part of the the section called “git(1)” suite
Run a Git command on a list of repositories. The arguments after the known options or -- indicator are used as the arguments for the Git subprocess.
THIS COMMAND IS EXPERIMENTAL. THE BEHAVIOR MAY CHANGE.
For example, we could run maintenance on each of a list of repositories stored in a maintenance.repo config variable using
git for-each-repo --config=maintenance.repo maintenance run
This will run git -C <repo> maintenance run for each value <repo> in the multi-valued config variable maintenance.repo.
Use the given config variable as a multi-valued list storing absolute path names. Iterate on that list of paths to run the given arguments.
These config values are loaded from system, global, and local Git config, as available. If git for-each-repo is run in a directory that is not a Git repository, then only the system and global config is used.
Continue with the remaining repositories if the command failed on a repository. The exit code will still indicate that the overall operation was not successful.
Note that the exact exit code of the failing command is not passed through as the exit code of the for-each-repo command: If the command failed in any of the specified repositories, the overall exit code will be 1.
If any git -C <repo> <arguments> subprocess returns a non-zero exit code, then the git for-each-repo process returns that exit code without running more subprocesses.
Each git -C <repo> <arguments> subprocess inherits the standard file descriptors stdin, stdout, and stderr.
Part of the the section called “git(1)” suite
git format-patch [-k] [(-o|--output-directory) <dir> | --stdout]
[--no-thread | --thread[=<style>]]
[(--attach|--inline)[=<boundary>] | --no-attach]
[-s | --signoff]
[--signature=<signature> | --no-signature]
[--signature-file=<file>]
[-n | --numbered | -N | --no-numbered]
[--start-number <n>] [--numbered-files]
[--in-reply-to=<message-id>] [--suffix=.<sfx>]
[--ignore-if-in-upstream] [--always]
[--cover-from-description=<mode>]
[--rfc[=<rfc>]] [--subject-prefix=<subject-prefix>]
[(--reroll-count|-v) <n>]
[--to=<email>] [--cc=<email>]
[--[no-]cover-letter] [--quiet]
[--[no-]encode-email-headers]
[--no-notes | --notes[=<ref>]]
[--interdiff=<previous>]
[--range-diff=<previous> [--creation-factor=<percent>]]
[--filename-max-length=<n>]
[--progress]
[<common-diff-options>]
[ <since> | <revision-range> ]
Prepare each non-merge commit with its "patch" in one "message" per commit, formatted to resemble a UNIX mailbox. The output of this command is convenient for e-mail submission or for use with git am.
A "message" generated by the command consists of three parts:
The log message and the patch are separated by a line with a three-dash line.
There are two ways to specify which commits to operate on.
The first rule takes precedence in the case of a single <commit>. To apply the second rule, i.e., format everything since the beginning of history up until <commit>, use the --root option: git format-patch --root <commit>. If you want to format only <commit> itself, you can do this with git format-patch -1 <commit>.
By default, each output file is numbered sequentially from 1, and uses the first line of the commit message (massaged for pathname safety) as the filename. With the --numbered-files option, the output file names will only be numbers, without the first line of the commit appended. The names of the output files are printed to standard output, unless the --stdout option is specified.
If -o is specified, output files are created in <dir>. Otherwise they are created in the current working directory. The default path can be set with the format.outputDirectory configuration option. The -o option takes precedence over format.outputDirectory. To store patches in the current working directory even when format.outputDirectory points elsewhere, use -o .. All directory components will be created.
By default, the subject of a single patch is "[PATCH] " followed by the concatenation of lines from the commit message up to the first blank line (see the DISCUSSION section of the section called “git-commit(1)”).
When multiple patches are output, the subject prefix will instead be "[PATCH n/m] ". To force 1/1 to be added for a single patch, use -n. To omit patch numbers from the subject, use -N.
If given --thread, git-format-patch will generate In-Reply-To and References headers to make the second and subsequent patch mails appear as replies to the first mail; this also generates a Message-ID header to reference.
Generate a diff using the "anchored diff" algorithm.
This option may be specified more than once.
If a line exists in both the source and destination, exists only once, and starts with <text>, this algorithm attempts to prevent it from appearing as a deletion or addition in the output. It uses the "patience diff" algorithm internally.
Choose a diff algorithm. The variants are as follows:
For instance, if you configured the diff.algorithm variable to a non-default value and want to use the default one, then you have to use --diff-algorithm=default option.
Generate a diffstat. By default, as much space as necessary will be used for the filename part, and the rest for the graph part. Maximum width defaults to terminal width, or 80 columns if not connected to a terminal, and can be overridden by <width>. The width of the filename part can be limited by giving another width <name-width> after a comma or by setting diff.statNameWidth=<name-width>. The width of the graph part can be limited by using --stat-graph-width=<graph-width> or by setting diff.statGraphWidth=<graph-width>. Using --stat or --stat-graph-width affects all commands generating a stat graph, while setting diff.statNameWidth or diff.statGraphWidth does not affect git format-patch. By giving a third parameter <count>, you can limit the output to the first <count> lines, followed by ... if there are more.
These parameters can also be set individually with --stat-width=<width>, --stat-name-width=<name-width> and --stat-count=<count>.
Output the distribution of relative amount of changes for each sub-directory. The behavior of --dirstat can be customized by passing it a comma separated list of parameters. The defaults are controlled by the diff.dirstat configuration variable (see the section called “git-config(1)”). The following parameters are available:
Example: The following will count changed files, while ignoring directories with less than 10% of the total amount of changed files, and accumulating child directory counts in the parent directories: --dirstat=files,10,cumulative.
Break complete rewrite changes into pairs of delete and create. This serves two purposes:
It affects the way a change that amounts to a total rewrite of a file not as a series of deletion and insertion mixed together with a very few lines that happen to match textually as the context, but as a single deletion of everything old followed by a single insertion of everything new, and the number <m> controls this aspect of the -B option (defaults to 60%). -B/70% specifies that less than 30% of the original should remain in the result for Git to consider it a total rewrite (i.e. otherwise the resulting patch will be a series of deletion and insertion mixed together with context lines).
When used with -M, a totally-rewritten file is also considered as the source of a rename (usually -M only considers a file that disappeared as the source of a rename), and the number <n> controls this aspect of the -B option (defaults to 50%). -B20% specifies that a change with addition and deletion compared to 20% or more of the file's size are eligible for being picked up as a possible source of a rename to another file.
Omit the preimage for deletes, i.e. print only the header but not the diff between the preimage and /dev/null. The resulting patch is not meant to be applied with patch or git apply; this is solely for people who want to just concentrate on reviewing the text after the change. In addition, the output obviously lacks enough information to apply such a patch in reverse, even manually, hence the name of the option.
When used together with -B, omit also the preimage in the deletion part of a delete/create pair.
Control the order in which files appear in the output. This overrides the diff.orderFile configuration variable (see the section called “git-config(1)”). To cancel diff.orderFile, use -O/dev/null.
The output order is determined by the order of glob patterns in <orderfile>. All files with pathnames that match the first pattern are output first, all files with pathnames that match the second pattern (but not the first) are output next, and so on. All files with pathnames that do not match any pattern are output last, as if there was an implicit match-all pattern at the end of the file. If multiple pathnames have the same rank (they match the same pattern but no earlier patterns), their output order relative to each other is the normal order.
<orderfile> is parsed as follows:
Patterns have the same syntax and semantics as patterns used for fnmatch(3) without the FNM_PATHNAME flag, except a pathname also matches a pattern if removing any number of the final pathname components matches the pattern. For example, the pattern "foo*bar" matches "fooasdfbar" and "foo/bar/baz/asdf" but not "foobarx".
For more detailed explanation on these common options, see also the section called “gitdiffcore(7)”.
Controls addition of In-Reply-To and References headers to make the second and subsequent mails appear as replies to the first. Also controls generation of the Message-ID header to reference.
The optional <style> argument can be either shallow or deep. shallow threading makes every mail a reply to the head of the series, where the head is chosen from the cover letter, the --in-reply-to, and the first patch mail, in this order. deep threading makes every mail a reply to the previous one.
The default is --no-thread, unless the format.thread configuration is set. --thread without an argument is equivalent to --thread=shallow.
Beware that the default for git send-email is to thread emails itself. If you want git format-patch to take care of threading, you will want to ensure that threading is disabled for git send-email.
Controls which parts of the cover letter will be automatically populated using the branch's description.
If <mode> is message or default, the cover letter subject will be populated with placeholder text. The body of the cover letter will be populated with the branch's description. This is the default mode when no configuration nor command line option is specified.
If <mode> is subject, the first paragraph of the branch description will populate the cover letter subject. The remainder of the description will populate the body of the cover letter.
If <mode> is auto, if the first paragraph of the branch description is greater than 100 bytes, then the mode will be message, otherwise subject will be used.
If <mode> is none, both the cover letter subject and body will be populated with placeholder text.
Instead of the standard [PATCH] prefix in the subject line, instead use [<subject-prefix>]. This can be used to name a patch series, and can be combined with the --numbered option.
The configuration variable format.subjectPrefix may also be used to configure a subject prefix to apply to a given repository for all patches. This is often useful on mailing lists which receive patches for several repositories and can be used to disambiguate the patches (with a value of e.g. "PATCH my-project").
Prepends the string <rfc> (defaults to "RFC") to the subject prefix. As the subject prefix defaults to "PATCH", you'll get "RFC PATCH" by default.
RFC means "Request For Comments"; use this when sending an experimental patch for discussion rather than application. "--rfc=WIP" may also be a useful way to indicate that a patch is not complete yet ("WIP" stands for "Work In Progress").
If the convention of the receiving community for a particular extra string is to have it after the subject prefix, the string <rfc> can be prefixed with a dash ("-") to signal that the rest of the <rfc> string should be appended to the subject prefix instead, e.g., --rfc='-(WIP)' results in "PATCH (WIP)".
Use ident in the From: header of each commit email. If the author ident of the commit is not textually identical to the provided ident, place a From: header in the body of the message with the original author. If no ident is given, use the committer ident.
Note that this option is only useful if you are actually sending the emails and want to identify yourself as the sender, but retain the original author (and git am will correctly pick up the in-body header). Note also that git send-email already handles this transformation for you, and this option should not be used if you are feeding the result to git send-email.
As a reviewer aid, insert a range-diff (see the section called “git-range-diff(1)”) into the cover letter, or as commentary of the lone patch of a 1-patch series, showing the differences between the previous version of the patch series and the series currently being formatted. previous can be a single revision naming the tip of the previous series if it shares a common base with the series being formatted (for example git format-patch --cover-letter --range-diff=feature/v1 -3 feature/v2), or a revision range if the two versions of the series are disjoint (for example git format-patch --cover-letter --range-diff=feature/v1~3..feature/v1 -3 feature/v2).
Note that diff options passed to the command affect how the primary product of format-patch is generated, and they are not passed to the underlying range-diff machinery used to generate the cover-letter material (this may change in the future).
Used with --range-diff, tweak the heuristic which matches up commits between the previous and current series of patches by adjusting the creation/deletion cost fudge factor. See the section called “git-range-diff(1)”) for details.
Defaults to 999 (the the section called “git-range-diff(1)” uses 60), as the use case is to show comparison with an older iteration of the same topic and the tool should find more correspondence between the two sets of patches.
Append the notes (see the section called “git-notes(1)”) for the commit after the three-dash line.
The expected use case of this is to write supporting explanation for the commit that does not belong to the commit log message proper, and include it with the patch submission. While one can simply write these explanations after format-patch has run but before sending, keeping them as Git notes allows them to be maintained between versions of the patch series (but see the discussion of the notes.rewrite configuration options in the section called “git-notes(1)” to use this workflow).
The default is --no-notes, unless the format.notes configuration is set.
Instead of using .patch as the suffix for generated filenames, use specified suffix. A common alternative is --suffix=.txt. Leaving this empty will remove the .patch suffix.
Note that the leading character does not have to be a dot; for example, you can use --suffix=-patch to get 0001-description-of-my-change-patch.
You can specify extra mail header lines to be added to each message, defaults for the subject prefix and file suffix, number patches when outputting more than one patch, add "To:" or "Cc:" headers, configure attachments, change the patch output directory, and sign off patches with configuration variables.
[format]
headers = "Organization: git-foo\n"
subjectPrefix = CHANGE
suffix = .txt
numbered = auto
to = <email>
cc = <email>
attach [ = mime-boundary-string ]
signOff = true
outputDirectory = <directory>
coverLetter = auto
coverFromDescription = autoThe patch produced by git format-patch is in UNIX mailbox format, with a fixed "magic" time stamp to indicate that the file is output from format-patch rather than a real mailbox, like so:
From 8f72bad1baf19a53459661343e21d6491c3908d3 Mon Sep 17 00:00:00 2001 From: Tony Luck <tony.luck@intel.com> Date: Tue, 13 Jul 2010 11:42:54 -0700 Subject: [PATCH] =?UTF-8?q?[IA64]=20Put=20ia64=20config=20files=20on=20the=20?= =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig=20diet?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit arch/arm config files were slimmed down using a python script (See commit c2330e286f68f1c408b4aa6515ba49d57f05beae comment) Do the same for ia64 so we can have sleek & trim looking ...
Typically it will be placed in a MUA's drafts folder, edited to add timely commentary that should not go in the changelog after the three dashes, and then sent as a message whose body, in our example, starts with "arch/arm config files were…". On the receiving end, readers can save interesting patches in a UNIX mailbox and apply them with the section called “git-am(1)”.
When a patch is part of an ongoing discussion, the patch generated by git format-patch can be tweaked to take advantage of the git am --scissors feature. After your response to the discussion comes a line that consists solely of "-- >8 --" (scissors and perforation), followed by the patch with unnecessary header fields removed:
... > So we should do such-and-such. Makes sense to me. How about this patch? -- >8 -- Subject: [IA64] Put ia64 config files on the Uwe Kleine-König diet arch/arm config files were slimmed down using a python script ...
When sending a patch this way, most often you are sending your own patch, so in addition to the "From $SHA1 $magic_timestamp" marker you should omit From: and Date: lines from the patch file. The patch title is likely to be different from the subject of the discussion the patch is in response to, so it is likely that you would want to keep the Subject: line, like the example above.
Many mailers if not set up properly will corrupt whitespace. Here are two common types of corruption:
One way to test if your MUA is set up correctly is:
Apply it:
$ git fetch <project> master:test-apply $ git switch test-apply $ git restore --source=HEAD --staged --worktree :/ $ git am a.patch
If it does not apply correctly, there can be various reasons.
Here are some hints on how to successfully submit patches inline using various mailers.
GMail does not have any way to turn off line wrapping in the web interface, so it will mangle any emails that you send. You can however use "git send-email" and send your patches through the GMail SMTP server, or use any IMAP email client to connect to the google IMAP server and forward the emails through that.
For hints on using git send-email to send your patches through the GMail SMTP server, see the EXAMPLE section of the section called “git-send-email(1)”.
For hints on submission using the IMAP interface, see the EXAMPLE section of the section called “git-imap-send(1)”.
By default, Thunderbird will both wrap emails as well as flag them as being format=flowed, both of which will make the resulting email unusable by Git.
There are three different approaches: use an add-on to turn off line wraps, configure Thunderbird to not mangle patches, or use an external editor to keep Thunderbird from mangling the patches.
Install the Toggle Word Wrap add-on that is available from https://addons.mozilla.org/thunderbird/addon/toggle-word-wrap/ It adds a menu entry "Enable Word Wrap" in the composer's "Options" menu that you can tick off. Now you can compose the message as you otherwise do (cut + paste, git format-patch | git imap-send, etc), but you have to insert line breaks manually in any text that you type.
Three steps:
Configure your general composition window to not wrap.
In Thunderbird 2: Edit..Preferences..Composition, wrap plain text messages at 0
In Thunderbird 3: Edit..Preferences..Advanced..Config Editor. Search for "mail.wrap_long_lines". Toggle it to make sure it is set to false. Also, search for "mailnews.wraplength" and set the value to 0.
After that is done, you should be able to compose email as you otherwise would (cut + paste, git format-patch | git imap-send, etc), and the patches will not be mangled.
The following Thunderbird extensions are needed: AboutConfig from https://mjg.github.io/AboutConfig/ and External Editor from https://globs.org/articles.php?lng=en&pg=8
In the main Thunderbird window, before you open the compose window for the patch, use Tools→about:config to set the following to the indicated values:
mailnews.send_plaintext_flowed => false
mailnews.wraplength => 0Side note: it may be possible to do step 2 with about:config and the following settings but no one's tried yet.
mail.html_compose => false
mail.identity.default.compose_html => false
mail.identity.id?.compose_html => falseThere is a script in contrib/thunderbird-patch-inline which can help you include patches with Thunderbird in an easy way. To use it, do the steps above and then use the script as the external editor.
This should help you to submit patches inline using KMail.
The base tree information block is used for maintainers or third party testers to know the exact state the patch series applies to. It consists of the base commit, which is a well-known commit that is part of the stable part of the project history everybody else works off of, and zero or more prerequisite patches, which are well-known patches in flight that is not yet part of the base commit that need to be applied on top of base commit in topological order before the patches can be applied.
The base commit is shown as "base-commit: " followed by the 40-hex of the commit object name. A prerequisite patch is shown as "prerequisite-patch-id: " followed by the 40-hex patch id, which can be obtained by passing the patch through the git patch-id --stable command.
Imagine that on top of the public commit P, you applied well-known patches X, Y and Z from somebody else, and then built your three-patch series A, B, C, the history would be like:
---P---X---Y---Z---A---B---C
With git format-patch --base=P -3 C (or variants thereof, e.g. with --cover-letter or using Z..C instead of -3 C to specify the range), the base tree information block is shown at the end of the first message the command outputs (either the first patch, or the cover letter), like this:
base-commit: P prerequisite-patch-id: X prerequisite-patch-id: Y prerequisite-patch-id: Z
For non-linear topology, such as
---P---X---A---M---C
\ /
Y---Z---BYou can also use git format-patch --base=P -3 C to generate patches for A, B and C, and the identifiers for P, X, Y, Z are appended at the end of the first message.
If set --base=auto in cmdline, it will automatically compute the base commit as the merge base of tip commit of the remote-tracking branch and revision-range specified in cmdline. For a local branch, you need to make it to track a remote branch by git branch --set-upstream-to before using this option.
Extract commits between revisions R1 and R2, and apply them on top of the current branch using git am to cherry-pick them:
$ git format-patch -k --stdout R1..R2 | git am -3 -k
Extract all commits which are in the current branch but not in the origin branch:
$ git format-patch origin
For each commit a separate file is created in the current directory.
Extract all commits that lead to origin since the inception of the project:
$ git format-patch --root origin
The same as the previous one:
$ git format-patch -M -B origin
Additionally, it detects and handles renames and complete rewrites intelligently to produce a renaming patch. A renaming patch reduces the amount of text output, and generally makes it easier to review. Note that non-Git "patch" programs won't understand renaming patches, so use it only when you know the recipient uses Git to apply your patch.
Extract three topmost commits from the current branch and format them as e-mailable patches:
$ git format-patch -3
Note that format-patch will omit merge commits from the output, even if they are part of the requested range. A simple "patch" does not include enough information for the receiving end to reproduce the same merge commit.
Part of the the section called “git(1)” suite
This is a synonym for the section called “git-fsck(1)”. Please refer to the documentation of that command.
Part of the the section called “git(1)” suite
git fsck [--tags] [--root] [--unreachable] [--cache] [--no-reflogs]
[--[no-]full] [--strict] [--verbose] [--lost-found]
[--[no-]dangling] [--[no-]progress] [--connectivity-only]
[--[no-]name-objects] [--[no-]references] [<object>…]
An object to treat as the head of an unreachability trace.
If no objects are given, git fsck defaults to using the index file, all SHA-1 references in the refs namespace, and all reflogs (unless --no-reflogs is given) as heads.
Check only the connectivity of reachable objects, making sure that any objects referenced by a reachable tag, commit, or tree are present. This speeds up the operation by avoiding reading blobs entirely (though it does still check that referenced blobs exist). This will detect corruption in commits and trees, but not do any semantic checks (e.g., for format errors). Corruption in blob objects will not be detected at all.
Unreachable tags, commits, and trees will also be accessed to find the tips of dangling segments of history. Use --no-dangling if you don't care about this output and want to speed it up further.
Everything below this line in this section is selectively included from the the section called “git-config(1)” documentation. The content is the same as what's found there:
During fsck git may find issues with legacy data which wouldn't be generated by current versions of git, and which wouldn't be sent over the wire if transfer.fsckObjects was set. This feature is intended to support working with legacy repositories containing such data.
Setting fsck.<msg-id> will be picked up by the section called “git-fsck(1)”, but to accept pushes of such data set receive.fsck.<msg-id> instead, or to clone or fetch it set fetch.fsck.<msg-id>.
The rest of the documentation discusses fsck.* for brevity, but the same applies for the corresponding receive.fsck.* and fetch.fsck.*. variables.
Unlike variables like color.ui and core.editor, the receive.fsck.<msg-id> and fetch.fsck.<msg-id> variables will not fall back on the fsck.<msg-id> configuration if they aren't set. To uniformly configure the same fsck settings in different circumstances, all three of them must be set to the same values.
When fsck.<msg-id> is set, errors can be switched to warnings and vice versa by configuring the fsck.<msg-id> setting where the <msg-id> is the fsck message ID and the value is one of error, warn or ignore. For convenience, fsck prefixes the error/warning with the message ID, e.g. "missingEmail: invalid author/committer line - missing email" means that setting fsck.missingEmail = ignore will hide that issue.
In general, it is better to enumerate existing objects with problems with fsck.skipList, instead of listing the kind of breakages these problematic objects share to be ignored, as doing the latter will allow new instances of the same breakages go unnoticed.
Setting an unknown fsck.<msg-id> value will cause fsck to die, but doing the same for receive.fsck.<msg-id> and fetch.fsck.<msg-id> will only cause git to warn.
See the Fsck Messages section of the section called “git-fsck(1)” for supported values of <msg-id>.
The path to a list of object names (i.e. one unabbreviated SHA-1 per line) that are known to be broken in a non-fatal way and should be ignored. On versions of Git 2.20 and later, comments (#), empty lines, and any leading and trailing whitespace are ignored. Everything but a SHA-1 per line will error out on older versions.
This feature is useful when an established project should be accepted despite early commits containing errors that can be safely ignored, such as invalid committer email addresses. Note: corrupt objects cannot be skipped with this setting.
Like fsck.<msg-id> this variable has corresponding receive.fsck.skipList and fetch.fsck.skipList variants.
Unlike variables like color.ui and core.editor the receive.fsck.skipList and fetch.fsck.skipList variables will not fall back on the fsck.skipList configuration if they aren't set. To uniformly configure the same fsck settings in different circumstances, all three of them must be set to the same values.
Older versions of Git (before 2.20) documented that the object names list should be sorted. This was never a requirement; the object names could appear in any order, but when reading the list we tracked whether the list was sorted for the purposes of an internal binary search implementation, which could save itself some work with an already sorted list. Unless you had a humongous list there was no reason to go out of your way to pre-sort the list. After Git version 2.20 a hash implementation is used instead, so there's now no reason to pre-sort the list.
git-fsck tests SHA-1 and general object sanity, and it does full tracking of the resulting reachability and everything else. It prints out any corruption it finds (missing or bad objects), and if you use the --unreachable flag it will also print out objects that exist but that aren't reachable from any of the specified head nodes (or the default set, as mentioned above).
Any corrupt objects you will have to find in backups or other archives (i.e., you can just remove them and do an rsync with some other site in the hopes that somebody else has the object you have corrupted).
If core.commitGraph is true, the commit-graph file will also be inspected using git commit-graph verify. See the section called “git-commit-graph(1)”.
The following lists the types of errors git fsck detects and what each error means, with their default severity. The severity of the error, other than those that are marked as "(FATAL)", can be tweaked by setting the corresponding fsck.<msg-id> configuration variable.
gitmodulesLarge; (ERROR) .gitmodules blob is too large to parse.
Part of the the section called “git(1)” suite
git fsmonitor--daemon start
git fsmonitor--daemon run
git fsmonitor--daemon stop
git fsmonitor--daemon status
A daemon to watch the working directory for file and directory changes using platform-specific filesystem notification facilities.
This daemon communicates directly with commands like git status using the simple IPC interface instead of the slower the section called “githooks(5)” interface.
This daemon is built into Git so that no third-party tools are required.
This daemon is a long running process used to watch a single working directory and maintain a list of the recently changed files and directories. Performance of commands such as git status can be increased if they just ask for a summary of changes to the working directory and can avoid scanning the disk.
When core.fsmonitor is set to true (see the section called “git-config(1)”) commands, such as git status, will ask the daemon for changes and automatically start it (if necessary).
For more information see the "File System Monitor" section in the section called “git-update-index(1)”.
The fsmonitor daemon does not currently know about submodules and does not know to filter out filesystem events that happen within a submodule. If fsmonitor daemon is watching a super repo and a file is modified within the working directory of a submodule, it will report the change (as happening against the super repo). However, the client will properly ignore these extra events, so performance may be affected but it will not cause an incorrect result.
By default, the fsmonitor daemon refuses to work with network-mounted repositories; this may be overridden by setting fsmonitor.allowRemote to true. Note, however, that the fsmonitor daemon is not guaranteed to work correctly with all network-mounted repositories, so such use is considered experimental.
On Mac OS, the inter-process communication (IPC) between various Git commands and the fsmonitor daemon is done via a Unix domain socket (UDS) -- a special type of file -- which is supported by native Mac OS filesystems, but not on network-mounted filesystems, NTFS, or FAT32. Other filesystems may or may not have the needed support; the fsmonitor daemon is not guaranteed to work with these filesystems and such use is considered experimental.
By default, the socket is created in the .git directory. However, if the .git directory is on a network-mounted filesystem, it will instead be created at $HOME/.git-fsmonitor-* unless $HOME itself is on a network-mounted filesystem, in which case you must set the configuration variable fsmonitor.socketDir to the path of a directory on a Mac OS native filesystem in which to create the socket file.
If none of the above directories (.git, $HOME, or fsmonitor.socketDir) is on a native Mac OS file filesystem the fsmonitor daemon will report an error that will cause the daemon and the currently running command to exit.
Everything below this line in this section is selectively included from the the section called “git-config(1)” documentation. The content is the same as what's found there:
Part of the the section called “git(1)” suite
git gc [--aggressive] [--auto] [--[no-]detach] [--quiet] [--prune=<date> | --no-prune] [--force] [--keep-largest-pack]
Runs a number of housekeeping tasks within the current repository, such as compressing file revisions (to reduce disk space and increase performance), removing unreachable objects which may have been created from prior invocations of git add, packing refs, pruning reflog, rerere metadata or stale working trees. May also update ancillary indexes such as the commit-graph.
When common porcelain operations that create objects are run, they will check whether the repository has grown substantially since the last maintenance, and if so run git gc automatically. See gc.auto below for how to disable this behavior.
Running git gc manually should only be needed when adding objects to a repository without regularly running such porcelain commands, to do a one-off repository optimization, or e.g. to clean up a suboptimal mass-import. See the "PACKFILE OPTIMIZATION" section in the section called “git-fast-import(1)” for more details on the import case.
With this option, git gc checks whether any housekeeping is required; if not, it exits without performing any work.
See the gc.auto option in the "CONFIGURATION" section below for how this heuristic works.
Once housekeeping is triggered by exceeding the limits of configuration options such as gc.auto and gc.autoPackLimit, all other housekeeping tasks (e.g. rerere, working trees, reflog…) will be performed as well.
When the --aggressive option is supplied, the section called “git-repack(1)” will be invoked with the -f flag, which in turn will pass --no-reuse-delta to the section called “git-pack-objects(1)”. This will throw away any existing deltas and re-compute them, at the expense of spending much more time on the repacking.
The effects of this are mostly persistent, e.g. when packs and loose objects are coalesced into one another pack the existing deltas in that pack might get re-used, but there are also various cases where we might pick a sub-optimal delta from a newer pack instead.
Furthermore, supplying --aggressive will tweak the --depth and --window options passed to the section called “git-repack(1)”. See the gc.aggressiveDepth and gc.aggressiveWindow settings below. By using a larger window size we're more likely to find more optimal deltas.
It's probably not worth it to use this option on a given repository without running tailored performance benchmarks on it. It takes a lot more time, and the resulting space/delta optimization may or may not be worth it. Not using this at all is the right trade-off for most users and their repositories.
Everything below this line in this section is selectively included from the the section called “git-config(1)” documentation. The content is the same as what's found there:
The depth parameter used in the delta compression algorithm used by git gc --aggressive. This defaults to 50, which is the default for the --depth option when --aggressive isn't in use.
See the documentation for the --depth option in the section called “git-repack(1)” for more details.
The window size parameter used in the delta compression algorithm used by git gc --aggressive. This defaults to 250, which is a much more aggressive window size than the default --window of 10.
See the documentation for the --window option in the section called “git-repack(1)” for more details.
When there are approximately more than this many loose objects in the repository, git gc --auto will pack them. Some Porcelain commands use this command to perform a light-weight garbage collection from time to time. The default value is 6700.
Setting this to 0 disables not only automatic packing based on the number of loose objects, but also any other heuristic git gc --auto will otherwise use to determine if there's work to do, such as gc.autoPackLimit.
When there are more than this many packs that are not marked with *.keep file in the repository, git gc --auto consolidates them into one larger pack. The default value is 50. Setting this to 0 disables it. Setting gc.auto to 0 will also disable this.
See the gc.bigPackThreshold configuration variable below. When in use, it'll affect how the auto pack limit works.
If non-zero, all non-cruft packs larger than this limit are kept when git gc is run. This is very similar to --keep-largest-pack except that all non-cruft packs that meet the threshold are kept, not just the largest pack. Defaults to zero. Common unit suffixes of k, m, or g are supported.
Note that if the number of kept packs is more than gc.autoPackLimit, this configuration variable is ignored, all packs except the base pack will be repacked. After this the number of packs should go below gc.autoPackLimit and gc.bigPackThreshold should be respected again.
If the amount of memory estimated for git repack to run smoothly is not available and gc.bigPackThreshold is not set, the largest pack will also be excluded (this is the equivalent of running git gc with --keep-largest-pack).
git reflog expire removes reflog entries older than this time and are not reachable from the current tip; defaults to 30 days. The value "now" expires all entries immediately, and "never" suppresses expiration altogether. With "<pattern>" (e.g. "refs/stash") in the middle, the setting applies only to the refs that match the <pattern>.
These types of entries are generally created as a result of using git commit --amend or git rebase and are the commits prior to the amend or rebase occurring. Since these changes are not part of the current project most users will want to expire them sooner, which is why the default is more aggressive than gc.reflogExpire.
When considering whether or not to remove an object (either when generating a cruft pack or storing unreachable objects as loose), use the shell to execute the specified command(s). Interpret their output as object IDs which Git will consider as "recent", regardless of their age. By treating their mtimes as "now", any objects (and their descendants) mentioned in the output will be kept regardless of their true age.
Output must contain exactly one hex object ID per line, and nothing else. Objects which cannot be found in the repository are ignored. Multiple hooks are supported, but all must exit successfully, else the operation (either generating a cruft pack or unpacking unreachable objects) will be halted.
git gc tries very hard not to delete objects that are referenced anywhere in your repository. In particular, it will keep not only objects referenced by your current set of branches and tags, but also objects referenced by the index, remote-tracking branches, reflogs (which may reference commits in branches that were later amended or rewound), and anything else in the refs/* namespace. Note that a note (of the kind created by git notes) attached to an object does not contribute in keeping the object alive. If you are expecting some objects to be deleted and they aren't, check all of those locations and decide whether it makes sense in your case to remove those references.
On the other hand, when git gc runs concurrently with another process, there is a risk of it deleting an object that the other process is using but hasn't created a reference to. This may just cause the other process to fail or may corrupt the repository if the other process later adds a reference to the deleted object. Git has two features that significantly mitigate this problem:
However, these features fall short of a complete solution, so users who run commands concurrently have to live with some risk of corruption (which seems to be low in practice).
The git gc --auto command will run the pre-auto-gc hook. See the section called “githooks(5)” for more information.
the section called “git-prune(1)” the section called “git-reflog(1)” the section called “git-repack(1)” the section called “git-rerere(1)”
Part of the the section called “git(1)” suite
Read a tar archive created by git archive from the standard input and extract the commit ID stored in it. It reads only the first 1024 bytes of input, thus its runtime is not influenced by the size of the tar archive very much.
If no commit ID is found, git get-tar-commit-id quietly exits with a return code of 1. This can happen if the archive had not been created using git archive or if the first parameter of git archive had been a tree ID instead of a commit ID or tag.
Part of the the section called “git(1)” suite
git grep [-a | --text] [-I] [--textconv] [-i | --ignore-case] [-w | --word-regexp]
[-v | --invert-match] [-h|-H] [--full-name]
[-E | --extended-regexp] [-G | --basic-regexp]
[-P | --perl-regexp]
[-F | --fixed-strings] [-n | --line-number] [--column]
[-l | --files-with-matches] [-L | --files-without-match]
[(-O | --open-files-in-pager) [<pager>]]
[-z | --null]
[ -o | --only-matching ] [-c | --count] [--all-match] [-q | --quiet]
[--max-depth <depth>] [--[no-]recursive]
[--color[=<when>] | --no-color]
[--break] [--heading] [-p | --show-function]
[-A <post-context>] [-B <pre-context>] [-C <context>]
[-W | --function-context]
[(-m | --max-count) <num>]
[--threads <num>]
[-f <file>] [-e] <pattern>
[--and|--or|--not|(|)|-e <pattern>…]
[--recurse-submodules] [--parent-basename <basename>]
[ [--[no-]exclude-standard] [--cached | --untracked | --no-index] | <tree>…]
[--] [<pathspec>…]
Look for specified patterns in the tracked files in the work tree, blobs registered in the index file, or blobs in given tree objects. Patterns are lists of one or more search expressions separated by newline characters. An empty string as search expression matches all lines.
Search files in the current directory that is not managed by Git, or by ignoring that the current directory is managed by Git. This is rather similar to running the regular grep(1) utility with its -r option specified, but with some additional benefits, such as using pathspec patterns to limit paths; see the pathspec entry in the section called “gitglossary(7)” for more information.
This option cannot be used together with --cached or --untracked. See also grep.fallbackToNoIndex in CONFIGURATION below.
Use Perl-compatible regular expressions for patterns.
Support for these types of regular expressions is an optional compile-time dependency. If Git wasn't compiled with support for them providing this option will cause it to die.
Read patterns from <file>, one per line.
Passing the pattern via <file> allows for providing a search pattern containing a \0.
Not all pattern types support patterns containing \0. Git will error out if a given pattern type can't support such a pattern. The --perl-regexp pattern type when compiled against the PCRE v2 backend has the widest support for these types of patterns.
In versions of Git before 2.23.0 patterns containing \0 would be silently considered fixed. This was never documented, there were also odd and undocumented interactions between e.g. non-ASCII patterns containing \0 and --ignore-case.
In future versions we may learn to support patterns containing \0 for more search backends, until then we'll die when the pattern type in question doesn't support them.
If given, limit the search to paths matching at least one pattern. Both leading paths match and glob(7) patterns are supported.
For more details about the <pathspec> syntax, see the pathspec entry in the section called “gitglossary(7)”.
The --threads option (and the grep.threads configuration) will be ignored when --open-files-in-pager is used, forcing a single-threaded execution.
When grepping the object store (with --cached or giving tree objects), running with multiple threads might perform slower than single-threaded if --textconv is given and there are too many text conversions. Thus, if low performance is experienced in this case, it might be desirable to use --threads=1.
Everything below this line in this section is selectively included from the the section called “git-config(1)” documentation. The content is the same as what's found there:
Part of the the section called “git(1)” suite
A Tcl/Tk based graphical user interface to Git. git gui focuses on allowing users to make changes to their repository by making new commits, amending existing ones, creating branches, performing local merges, and fetching/pushing to remote repositories.
Unlike gitk, git gui focuses on commit generation and single file annotation and does not show project history. It does however supply menu actions to start a gitk session from within git gui.
git gui is known to work on all popular UNIX systems, Mac OS X, and Windows (under both Cygwin and MSYS). To the extent possible OS specific user interface guidelines are followed, making git gui a fairly native interface for users.
git gui is actually maintained as an independent project, but stable versions are distributed as part of the Git suite for the convenience of end users.
The official repository of the git gui project can be found at:
https://github.com/j6t/git-gui
Part of the the section called “git(1)” suite
git hash-object [-t <type>] [-w] [--path=<file> | --no-filters]
[--stdin [--literally]] [--] <file>…
git hash-object [-t <type>] [-w] --stdin-paths [--no-filters]
Computes the object ID value for an object with specified type with the contents of the named file (which can be outside of the work tree), and optionally writes the resulting object into the object database. Reports its object ID to its standard output. When <type> is not specified, it defaults to "blob".
Part of the the section called “git(1)” suite
git help [-a|--all] [--[no-]verbose] [--[no-]external-commands] [--[no-]aliases]
git help [[-i|--info] [-m|--man] [-w|--web]] [<command>|<doc>]
git help [-g|--guides]
git help [-c|--config]
git help [--user-interfaces]
git help [--developer-interfaces]
With no options and no <command> or <doc> given, the synopsis of the git command and a list of the most commonly used Git commands are printed on the standard output.
If the option --all or -a is given, all available commands are printed on the standard output.
If the option --guides or -g is given, a list of the Git concept guides is also printed on the standard output.
If a command or other documentation is given, the relevant manual page will be brought up. The man program is used by default for this purpose, but this can be overridden by other options or configuration variables.
If an alias is given, git shows the definition of the alias on standard output. To get the manual page for the aliased command, use git <command> --help.
Note that git --help ... is identical to git help ... because the former is internally converted into the latter.
To display the the section called “git(1)” man page, use git help git.
This page can be displayed with git help help or git help --help.
Print a list of the repository, command and file interfaces documentation on the standard output.
In-repository file interfaces such as .git/info/exclude are documented here (see the section called “gitrepository-layout(5)”), as well as in-tree configuration such as .mailmap (see the section called “gitmailmap(5)”).
This section of the documentation also covers general or widespread user-interface conventions (e.g. the section called “gitcli(7)”), and pseudo-configuration such as the file-based .git/hooks/* interface described in the section called “githooks(5)”.
Display manual page for the command in the man format. This option may be used to override a value set in the help.format configuration variable.
By default the man program will be used to display the manual page, but the man.viewer configuration variable may be used to choose other display programs (see below).
Display manual page for the command in the web (HTML) format. A web browser will be used for that purpose.
The web browser can be specified using the configuration variable help.browser, or web.browser if the former is not set. If neither of these config variables is set, the git web--browse helper script (called by git help) will pick a suitable default. See the section called “git-web--browse(1)” for more information about this.
If no command-line option is passed, the help.format configuration variable will be checked. The following values are supported for this variable; they make git help behave as their corresponding command- line option:
The help.browser, web.browser and browser.<tool>.path will also be checked if the web format is chosen (either by command-line option or configuration variable). See -w|--web in the OPTIONS section above and the section called “git-web--browse(1)”.
The man.viewer configuration variable will be checked if the man format is chosen. The following values are currently supported:
Values for other tools can be used if there is a corresponding man.<tool>.cmd configuration entry (see below).
Multiple values may be given to the man.viewer configuration variable. Their corresponding programs will be tried in the order listed in the configuration file.
For example, this configuration:
[man]
viewer = konqueror
viewer = womanwill try to use konqueror first. But this may fail (for example, if DISPLAY is not set) and in that case emacs' woman mode will be tried.
If everything fails, or if no viewer is configured, the viewer specified in the GIT_MAN_VIEWER environment variable will be tried. If that fails too, the man program will be tried anyway.
You can explicitly provide a full path to your preferred man viewer by setting the configuration variable man.<tool>.path. For example, you can configure the absolute path to konqueror by setting man.konqueror.path. Otherwise, git help assumes the tool is available in PATH.
When the man viewer, specified by the man.viewer configuration variables, is not among the supported ones, then the corresponding man.<tool>.cmd configuration variable will be looked up. If this variable exists then the specified tool will be treated as a custom command and a shell eval will be used to run the command with the man page passed as arguments.
When konqueror is specified in the man.viewer configuration variable, we launch kfmclient to try to open the man page on an already opened konqueror in a new tab if possible.
For consistency, we also try such a trick if man.konqueror.path is set to something like A_PATH_TO/konqueror. That means we will try to launch A_PATH_TO/kfmclient instead.
If you really want to use konqueror, then you can use something like the following:
[man]
viewer = konq
[man "konq"]
cmd = A_PATH_TO/konquerorNote that all these configuration variables should probably be set using the --global flag, for example like this:
$ git config --global help.format web $ git config --global web.browser firefox
as they are probably more user specific than repository specific. See the section called “git-config(1)” for more information about this.
Part of the the section called “git(1)” suite
A command interface for running git hooks (see the section called “githooks(5)”), for use by other scripted git commands.
Run the <hook-name> hook. See the section called “githooks(5)” for supported hook names.
Any positional arguments to the hook should be passed after a mandatory -- (or --end-of-options, see the section called “gitcli(7)”). See the section called “githooks(5)” for arguments hooks might expect (if any).
Part of the the section called “git(1)” suite
A simple CGI program to serve the contents of a Git repository to Git clients accessing the repository over http:// and https:// protocols. The program supports clients fetching using both the smart HTTP protocol and the backwards-compatible dumb HTTP protocol, as well as clients pushing using the smart HTTP protocol. It also supports Git's more-efficient "v2" protocol if properly configured; see the discussion of GIT_PROTOCOL in the ENVIRONMENT section below.
It verifies that the directory has the magic file "git-daemon-export-ok", and it will refuse to export any Git directory that hasn't explicitly been marked for export this way (unless the GIT_HTTP_EXPORT_ALL environment variable is set).
By default, only the upload-pack service is enabled, which serves git fetch-pack and git ls-remote clients, which are invoked from git fetch, git pull, and git clone. If the client is authenticated, the receive-pack service is enabled, which serves git send-pack clients, which is invoked from git push.
These services can be enabled/disabled using the per-repository configuration file:
To determine the location of the repository on disk, git http-backend concatenates the environment variables PATH_INFO, which is set automatically by the web server, and GIT_PROJECT_ROOT, which must be set manually in the web server configuration. If GIT_PROJECT_ROOT is not set, git http-backend reads PATH_TRANSLATED, which is also set automatically by the web server.
All of the following examples map http://$hostname/git/foo/bar.git to /var/www/git/foo/bar.git.
Ensure mod_cgi, mod_alias, and mod_env are enabled, set GIT_PROJECT_ROOT (or DocumentRoot) appropriately, and create a ScriptAlias to the CGI:
SetEnv GIT_PROJECT_ROOT /var/www/git SetEnv GIT_HTTP_EXPORT_ALL ScriptAlias /git/ /usr/libexec/git-core/git-http-backend/ # This is not strictly necessary using Apache and a modern version of # git-http-backend, as the webserver will pass along the header in the # environment as HTTP_GIT_PROTOCOL, and http-backend will copy that into # GIT_PROTOCOL. But you may need this line (or something similar if you # are using a different webserver), or if you want to support older Git # versions that did not do that copying. # # Having the webserver set up GIT_PROTOCOL is perfectly fine even with # modern versions (and will take precedence over HTTP_GIT_PROTOCOL, # which means it can be used to override the client's request). SetEnvIf Git-Protocol ".*" GIT_PROTOCOL=$0
To enable anonymous read access but authenticated write access, require authorization for both the initial ref advertisement (which we detect as a push via the service parameter in the query string), and the receive-pack invocation itself:
RewriteCond %{QUERY_STRING} service=git-receive-pack [OR]
RewriteCond %{REQUEST_URI} /git-receive-pack$
RewriteRule ^/git/ - [E=AUTHREQUIRED:yes]
<LocationMatch "^/git/">
Order Deny,Allow
Deny from env=AUTHREQUIRED
AuthType Basic
AuthName "Git Access"
Require group committers
Satisfy Any
...
</LocationMatch>If you do not have mod_rewrite available to match against the query string, it is sufficient to just protect git-receive-pack itself, like:
<LocationMatch "^/git/.*/git-receive-pack$">
AuthType Basic
AuthName "Git Access"
Require group committers
...
</LocationMatch>In this mode, the server will not request authentication until the client actually starts the object negotiation phase of the push, rather than during the initial contact. For this reason, you must also enable the http.receivepack config option in any repositories that should accept a push. The default behavior, if http.receivepack is not set, is to reject any pushes by unauthenticated users; the initial request will therefore report 403 Forbidden to the client, without even giving an opportunity for authentication.
To require authentication for both reads and writes, use a Location directive around the repository, or one of its parent directories:
<Location /git/private>
AuthType Basic
AuthName "Private Git Access"
Require group committers
...
</Location>To serve gitweb at the same url, use a ScriptAliasMatch to only those URLs that git http-backend can handle, and forward the rest to gitweb:
ScriptAliasMatch \
"(?x)^/git/(.*/(HEAD | \
info/refs | \
objects/(info/[^/]+ | \
[0-9a-f]{2}/[0-9a-f]{38} | \
pack/pack-[0-9a-f]{40}\.(pack|idx)) | \
git-(upload|receive)-pack))$" \
/usr/libexec/git-core/git-http-backend/$1
ScriptAlias /git/ /var/www/cgi-bin/gitweb.cgi/To serve multiple repositories from different the section called “gitnamespaces(7)” in a single repository:
SetEnvIf Request_URI "^/git/([^/]*)" GIT_NAMESPACE=$1 ScriptAliasMatch ^/git/[^/]*(.*) /usr/libexec/git-core/git-http-backend/storage.git$1
Similar to the above, but Apache can be used to return static files that are stored on disk. On many systems this may be more efficient as Apache can ask the kernel to copy the file contents from the file system directly to the network:
SetEnv GIT_PROJECT_ROOT /var/www/git
AliasMatch ^/git/(.*/objects/[0-9a-f]{2}/[0-9a-f]{38})$ /var/www/git/$1
AliasMatch ^/git/(.*/objects/pack/pack-[0-9a-f]{40}.(pack|idx))$ /var/www/git/$1
ScriptAlias /git/ /usr/libexec/git-core/git-http-backend/This can be combined with the gitweb configuration:
SetEnv GIT_PROJECT_ROOT /var/www/git
AliasMatch ^/git/(.*/objects/[0-9a-f]{2}/[0-9a-f]{38})$ /var/www/git/$1
AliasMatch ^/git/(.*/objects/pack/pack-[0-9a-f]{40}.(pack|idx))$ /var/www/git/$1
ScriptAliasMatch \
"(?x)^/git/(.*/(HEAD | \
info/refs | \
objects/info/[^/]+ | \
git-(upload|receive)-pack))$" \
/usr/libexec/git-core/git-http-backend/$1
ScriptAlias /git/ /var/www/cgi-bin/gitweb.cgi/Ensure that mod_cgi, mod_alias, mod_auth, mod_setenv are loaded, then set GIT_PROJECT_ROOT appropriately and redirect all requests to the CGI:
alias.url += ( "/git" => "/usr/lib/git-core/git-http-backend" )
$HTTP["url"] =~ "^/git" {
cgi.assign = ("" => "")
setenv.add-environment = (
"GIT_PROJECT_ROOT" => "/var/www/git",
"GIT_HTTP_EXPORT_ALL" => ""
)
}To enable anonymous read access but authenticated write access:
$HTTP["querystring"] =~ "service=git-receive-pack" {
include "git-auth.conf"
}
$HTTP["url"] =~ "^/git/.*/git-receive-pack$" {
include "git-auth.conf"
}where git-auth.conf looks something like:
auth.require = (
"/" => (
"method" => "basic",
"realm" => "Git Access",
"require" => "valid-user"
)
)
# ...and set up auth.backend hereTo require authentication for both reads and writes:
$HTTP["url"] =~ "^/git/private" {
include "git-auth.conf"
}git http-backend relies upon the CGI environment variables set by the invoking web server, including:
The GIT_HTTP_EXPORT_ALL environment variable may be passed to git-http-backend to bypass the check for the "git-daemon-export-ok" file in each repository before allowing export of that repository.
The GIT_HTTP_MAX_REQUEST_BUFFER environment variable (or the http.maxRequestBuffer config option) may be set to change the largest ref negotiation request that git will handle during a fetch; any fetch requiring a larger buffer will not succeed. This value should not normally need to be changed, but may be helpful if you are fetching from a repository with an extremely large number of refs. The value can be specified with a unit (e.g., 100M for 100 megabytes). The default is 10 megabytes.
Clients may probe for optional protocol capabilities (like the v2 protocol) using the Git-Protocol HTTP header. In order to support these, the contents of that header must appear in the GIT_PROTOCOL environment variable. Most webservers will pass this header to the CGI via the HTTP_GIT_PROTOCOL variable, and git-http-backend will automatically copy that to GIT_PROTOCOL. However, some webservers may be more selective about which headers they'll pass, in which case they need to be configured explicitly (see the mention of Git-Protocol in the Apache config from the earlier EXAMPLES section).
The backend process sets GIT_COMMITTER_NAME to $REMOTE_USER and GIT_COMMITTER_EMAIL to ${REMOTE_USER}@http.${REMOTE_ADDR}, ensuring that any reflogs created by git-receive-pack contain some identifying information of the remote user who performed the push.
All CGI environment variables are available to each of the hooks invoked by the git-receive-pack.
Part of the the section called “git(1)” suite
git http-fetch [-c] [-t] [-a] [-d] [-v] [-w <filename>] [--recover] [--stdin | --packfile=<hash> | <commit>] <URL>
Downloads a remote Git repository via HTTP.
This command always gets all objects. Historically, there were three options -a, -c and -t for choosing which objects to download. They are now silently ignored.
Instead of a commit id on the command line (which is not expected in this case), git http-fetch expects lines on stdin in the format
<commit-id>['\t'<filename-as-in--w>]
Part of the the section called “git(1)” suite
Sends missing objects to the remote repository, and updates the remote branch.
NOTE: This command is temporarily disabled if your libcurl is older than 7.16, as the combination has been reported not to work and sometimes corrupts the repository.
Remove <ref> from remote repository. The specified branch cannot be the remote HEAD. If -d is specified, the following other conditions must also be met:
A <ref> specification can be either a single pattern, or a pair of such patterns separated by a colon ":" (this means that a ref name cannot have a colon in it). A single pattern <name> is just a shorthand for <name>:<name>.
Each pattern pair <src>:<dst> consists of the source side (before the colon) and the destination side (after the colon). The ref to be pushed is determined by finding a match that matches the source side, and where it is pushed is determined by using the destination side.
If <dst> does not match any remote ref, either
Without --force`, the <src> ref is stored at the remote only if <dst> does not exist, or <dst> is a proper subset (i.e. an ancestor) of <src>. This check, known as "fast-forward check", is performed to avoid accidentally overwriting the remote ref and losing other peoples commits from there.
With --force, the fast-forward check is disabled for all refs.
Optionally, a <ref> parameter can be prefixed with a plus + sign to disable the fast-forward check only on that ref.
Part of the the section called “git(1)” suite
This command uploads a mailbox generated with git format-patch into an IMAP drafts folder. This allows patches to be sent as other email is when using mail clients that cannot read mailbox files directly. The command also works with any general mailbox in which emails have the fields "From", "Date", and "Subject" in that order.
Typical usage is something like:
git format-patch --signoff --stdout --attach origin | git imap-send
To use the tool, imap.folder and either imap.tunnel or imap.host must be set to appropriate values.
Everything above this line in this section isn't included from the the section called “git-config(1)” documentation. The content that follows is the same as what's found there:
Using tunnel mode:
[imap]
folder = "INBOX.Drafts"
tunnel = "ssh -q -C user@example.com /usr/bin/imapd ./Maildir 2> /dev/null"Using direct mode:
[imap]
folder = "INBOX.Drafts"
host = imap://imap.example.com
user = bob
pass = p4ssw0rdUsing direct mode with SSL:
[imap]
folder = "INBOX.Drafts"
host = imaps://imap.example.com
user = bob
pass = p4ssw0rd
port = 123
; sslVerify = falseYou may want to use sslVerify=false while troubleshooting, if you suspect that the reason you are having trouble connecting is because the certificate you use at the private server example.com you are trying to set up (or have set up) may not be verified correctly.
Using Gmail's IMAP interface:
[imap]
folder = "[Gmail]/Drafts"
host = imaps://imap.gmail.com
user = user@gmail.com
port = 993You might need to instead use: folder = "[Google Mail]/Drafts" if you get an error that the "Folder doesn't exist".
If your Gmail account is set to another language than English, the name of the "Drafts" folder will be localized.
Once the commits are ready to be sent, run the following command:
$ git format-patch --cover-letter -M --stdout origin/master | git imap-send
Just make sure to disable line wrapping in the email client (Gmail's web interface will wrap lines no matter what, so you need to use a real IMAP client).
It is still your responsibility to make sure that the email message sent by your email program meets the standards of your project. Many projects do not like patches to be attached. Some mail agents will transform patches (e.g. wrap lines, send them as format=flowed) in ways that make them fail. You will get angry flames ridiculing you if you don't check this.
Thunderbird in particular is known to be problematic. Thunderbird users may wish to visit this web page for more information: https://kb.mozillazine.org/Plain_text_e-mail_-_Thunderbird#Completely_plain_email
Part of the the section called “git(1)” suite
git index-pack [-v] [-o <index-file>] [--[no-]rev-index] <pack-file>
git index-pack --stdin [--fix-thin] [--keep] [-v] [-o <index-file>]
[--[no-]rev-index] [<pack-file>]
Reads a packed archive (.pack) from the specified file, builds a pack index file (.idx) for it, and optionally writes a reverse-index (.rev) for the specified pack. The packed archive, together with the pack index, can then be placed in the objects/pack/ directory of a Git repository.
For internal use only.
Set the title of the progress bar. The title is "Receiving objects" by default and "Indexing objects" when --stdin is specified.
Die if the pack contains broken objects, but unlike --strict, don't choke on broken links. If the pack contains a tree pointing to a .gitmodules blob that does not exist, prints the hash of that blob (for the caller to check) after the hash that goes into the name of the pack/idx file (see "Notes").
An optional comma-separated list of <msg-id>=<severity> can be passed to change the severity of some possible issues, e.g., --fsck-objects="missingEmail=ignore,badTagName=ignore". See the entry for the fsck.<msg-id> configuration options in the section called “git-fsck(1)” for more information on the possible values of <msg-id> and <severity>.
Specify the given object format (hash algorithm) for the pack. The valid values are sha1 and (if enabled) sha256. The default is the algorithm for the current repository (set by extensions.objectFormat), or sha1 if no value is set or outside a repository.
This option cannot be used with --stdin.
Note: At present, there is no interoperability between SHA-256 repositories and SHA-1 repositories.
Historically, we warned that SHA-256 repositories may later need backward incompatible changes when we introduce such interoperability features. Today, we only expect compatible changes. Furthermore, if such changes prove to be necessary, it can be expected that SHA-256 repositories created with today's Git will be usable by future versions of Git without data loss.
Before committing the pack-index, create a .promisor file for this pack. Particularly helpful when writing a promisor pack with --fix-thin since the name of the pack is not final until the pack has been fully written. If a <message> is provided, then that content will be written to the .promisor file for future reference. See partial clone for more information.
Also, if there are objects in the given pack that references non-promisor objects (in the repo), repacks those non-promisor objects into a promisor pack. This avoids a situation in which a repo has non-promisor objects that are accessible through promisor objects.
Requires <pack-file> to not be specified.
Once the index has been created, the hash that goes into the name of the pack/idx file is printed to stdout. If --stdin was also used then this is prefixed by either "pack\t", or "keep\t" if a new .keep file was successfully created. This is useful to remove a .keep file used as a lock to prevent the race with git repack mentioned above.
Part of the the section called “git(1)” suite
git init-db [-q | --quiet] [--bare] [--template=<template-directory>] [--separate-git-dir <git-dir>] [--shared[=<permissions>]]
This is a synonym for the section called “git-init(1)”. Please refer to the documentation of that command.
Part of the the section called “git(1)” suite
gitinit[-q|--quiet] [--bare] [--template=<template-directory>]
[--separate-git-dir<git-dir>] [--object-format=<format>]
[--ref-format=<format>]
[-b<branch-name> |--initial-branch=<branch-name>]
[--shared[=<permissions>]] [<directory>]
This command creates an empty Git repository - basically a .git directory with subdirectories for objects, refs/heads, refs/tags, and template files. An initial branch without any commits will be created (see the --initial-branch option below for its name).
If the GIT_DIR environment variable is set then it specifies a path to use instead of ./.git for the base of the repository.
If the object storage directory is specified via the GIT_OBJECT_DIRECTORY environment variable then the sha1 directories are created underneath; otherwise, the default $GIT_DIR/objects directory is used.
Running git init in an existing repository is safe. It will not overwrite things that are already there. The primary reason for rerunning git init is to pick up newly added templates (or to move the repository to another place if --separate-git-dir is given).
Specify the given object <format> (hash algorithm) for the repository. The valid values are sha1 and (if enabled) sha256. sha1 is the default.
Note: At present, there is no interoperability between SHA-256 repositories and SHA-1 repositories.
Historically, we warned that SHA-256 repositories may later need backward incompatible changes when we introduce such interoperability features. Today, we only expect compatible changes. Furthermore, if such changes prove to be necessary, it can be expected that SHA-256 repositories created with today's Git will be usable by future versions of Git without data loss.
Specify the given ref storage <format> for the repository. The valid values are:
Instead of initializing the repository as a directory to either $GIT_DIR or ./.git/, create a text file there containing the path to the actual repository. This file acts as a filesystem-agnostic Git symbolic link to the repository.
If this is a reinitialization, the repository will be moved to the specified path.
Specify that the Git repository is to be shared amongst several users. This allows users belonging to the same group to push into that repository. When specified, the config variable core.sharedRepository is set so that files and directories under $GIT_DIR are created with the requested permissions. When not specified, Git will use permissions reported by umask(2).
The option can have the following values, defaulting to group if no value is given:
By default, the configuration flag receive.denyNonFastForwards is enabled in shared repositories, so that you cannot force a non fast-forwarding push into it.
If you provide a <directory>, the command is run inside it. If this directory does not exist, it will be created.
Files and directories in the template directory whose name do not start with a dot will be copied to the $GIT_DIR after it is created.
The template directory will be one of the following (in order):
The default template directory includes some directory structure, suggested "exclude patterns" (see the section called “gitignore(5)”), and sample hook files.
The sample hooks are all disabled by default. To enable one of the sample hooks rename it by removing its .sample suffix.
See the section called “githooks(5)” for more general info on hook execution.
Everything below this line in this section is selectively included from the the section called “git-config(1)” documentation. The content is the same as what's found there:
Part of the the section called “git(1)” suite
git instaweb [--local] [--httpd=<httpd>] [--port=<port>]
[--browser=<browser>]
git instaweb [--start] [--stop] [--restart]
You may specify configuration in your .git/config
[instaweb]
local = true
httpd = apache2 -f
port = 4321
browser = konqueror
modulePath = /usr/lib/apache2/modulesIf the configuration variable instaweb.browser is not set, web.browser will be used instead if it is defined. See the section called “git-web--browse(1)” for more information about this.
Part of the the section called “git(1)” suite
git interpret-trailers [--in-place] [--trim-empty]
[(--trailer (<key>|<key-alias>)[(=|:)<value>])…]
[--parse] [<file>…]
Add or parse trailer lines that look similar to RFC 822 e-mail headers, at the end of the otherwise free-form part of a commit message. For example, in the following commit message
subject Lorem ipsum dolor sit amet, consectetur adipiscing elit. Signed-off-by: Alice <alice@example.com> Signed-off-by: Bob <bob@example.com>
the last two lines starting with "Signed-off-by" are trailers.
This command reads commit messages from either the <file> arguments or the standard input if no <file> is specified. If --parse is specified, the output consists of the parsed trailers coming from the input, without influencing them with any command line options or configuration variables.
Otherwise, this command applies trailer.* configuration variables (which could potentially add new trailers, as well as reposition them), as well as any command line arguments that can override configuration variables (such as --trailer=... which could also add new trailers), to each input file. The result is emitted on the standard output.
This command can also operate on the output of the section called “git-format-patch(1)”, which is more elaborate than a plain commit message. Namely, such output includes a commit message (as above), a "---" divider line, and a patch part. For these inputs, the divider and patch parts are not modified by this command and are emitted as is on the output, unless --no-divider is specified.
Some configuration variables control the way the --trailer arguments are applied to each input and the way any existing trailer in the input is changed. They also make it possible to automatically add some trailers.
By default, a <key>=<value> or <key>:<value> argument given using --trailer will be appended after the existing trailers only if the last trailer has a different (<key>, <value>) pair (or if there is no existing trailer). The <key> and <value> parts will be trimmed to remove starting and trailing whitespace, and the resulting trimmed <key> and <value> will appear in the output like this:
key: value
This means that the trimmed <key> and <value> will be separated by ': ' (one colon followed by one space).
For convenience, a <key-alias> can be configured to make using --trailer shorter to type on the command line. This can be configured using the trailer.<key-alias>.key configuration variable. The <keyAlias> must be a prefix of the full <key> string, although case sensitivity does not matter. For example, if you have
trailer.sign.key "Signed-off-by: "
in your configuration, you only need to specify --trailer="sign: foo" on the command line instead of --trailer="Signed-off-by: foo".
By default the new trailer will appear at the end of all the existing trailers. If there is no existing trailer, the new trailer will appear at the end of the input. A blank line will be added before the new trailer if there isn't one already.
Existing trailers are extracted from the input by looking for a group of one or more lines that (i) is all trailers, or (ii) contains at least one Git-generated or user-configured trailer and consists of at least 25% trailers. The group must be preceded by one or more empty (or whitespace-only) lines. The group must either be at the end of the input or be the last non-whitespace lines before a line that starts with --- (followed by a space or the end of the line).
When reading trailers, there can be no whitespace before or inside the <key>, but any number of regular space and tab characters are allowed between the <key> and the separator. There can be whitespaces before, inside or after the <value>. The <value> may be split over multiple lines with each subsequent line starting with at least one whitespace, like the "folding" in RFC 822. Example:
key: This is a very long value, with spaces and newlines in it.
Note that trailers do not follow (nor are they intended to follow) many of the rules for RFC 822 headers. For example they do not follow the encoding rule.
Everything below this line in this section is selectively included from the the section called “git-config(1)” documentation. The content is the same as what's found there:
This option tells which characters are recognized as trailer separators. By default only : is recognized as a trailer separator, except that = is always accepted on the command line for compatibility with other git commands.
The first character given by this option will be the default character used when another separator is not specified in the config for this trailer.
For example, if the value for this option is "%=$", then only lines using the format <key><sep><value> with <sep> containing %, = or $ and then spaces will be considered trailers. And % will be the default separator used, so by default trailers will appear like: <key>% <value> (one percent sign and one space will appear between the key and the value).
This option tells where a new trailer will be added.
This can be end, which is the default, start, after or before.
If it is end, then each new trailer will appear at the end of the existing trailers.
If it is start, then each new trailer will appear at the start, instead of the end, of the existing trailers.
If it is after, then each new trailer will appear just after the last trailer with the same <key>.
If it is before, then each new trailer will appear just before the first trailer with the same <key>.
This option makes it possible to choose what action will be performed when there is already at least one trailer with the same <key> in the input.
The valid values for this option are: addIfDifferentNeighbor (this is the default), addIfDifferent, add, replace or doNothing.
With addIfDifferentNeighbor, a new trailer will be added only if no trailer with the same (<key>, <value>) pair is above or below the line where the new trailer will be added.
With addIfDifferent, a new trailer will be added only if no trailer with the same (<key>, <value>) pair is already in the input.
With add, a new trailer will be added, even if some trailers with the same (<key>, <value>) pair are already in the input.
With replace, an existing trailer with the same <key> will be deleted and the new trailer will be added. The deleted trailer will be the closest one (with the same <key>) to the place where the new one will be added.
With doNothing, nothing will be done; that is no new trailer will be added if there is already one with the same <key> in the input.
This option makes it possible to choose what action will be performed when there is not yet any trailer with the same <key> in the input.
The valid values for this option are: add (this is the default) and doNothing.
With add, a new trailer will be added.
With doNothing, nothing will be done.
Defines a <keyAlias> for the <key>. The <keyAlias> must be a prefix (case does not matter) of the <key>. For example, in git config trailer.ack.key "Acked-by" the "Acked-by" is the <key> and the "ack" is the <keyAlias>. This configuration allows the shorter --trailer "ack:..." invocation on the command line using the "ack" <keyAlias> instead of the longer --trailer "Acked-by:...".
At the end of the <key>, a separator can appear and then some space characters. By default the only valid separator is :, but this can be changed using the trailer.separators config variable.
If there is a separator in the key, then it overrides the default separator when adding the trailer.
Deprecated in favor of trailer.<keyAlias>.cmd. This option behaves in the same way as trailer.<keyAlias>.cmd, except that it doesn't pass anything as argument to the specified command. Instead the first occurrence of substring $ARG is replaced by the <value> that would be passed as argument.
Note that $ARG in the user's command is only replaced once and that the original way of replacing $ARG is not safe.
When both trailer.<keyAlias>.cmd and trailer.<keyAlias>.command are given for the same <keyAlias>, trailer.<keyAlias>.cmd is used and trailer.<keyAlias>.command is ignored.
This option can be used to specify a shell command that will be called once to automatically add a trailer with the specified <keyAlias>, and then called each time a --trailer <keyAlias>=<value> argument is specified to modify the <value> of the trailer that this option would produce.
When the specified command is first called to add a trailer with the specified <keyAlias>, the behavior is as if a special --trailer <keyAlias>=<value> argument was added at the beginning of the "git interpret-trailers" command, where <value> is taken to be the standard output of the command with any leading and trailing whitespace trimmed off.
If some --trailer <keyAlias>=<value> arguments are also passed on the command line, the command is called again once for each of these arguments with the same <keyAlias>. And the <value> part of these arguments, if any, will be passed to the command as its first argument. This way the command can produce a <value> computed from the <value> passed in the --trailer <keyAlias>=<value> argument.
Configure a sign trailer with a Signed-off-by key, and then add two of these trailers to a commit message file:
$ git config trailer.sign.key "Signed-off-by" $ cat msg.txt subject body text $ git interpret-trailers --trailer 'sign: Alice <alice@example.com>' --trailer 'sign: Bob <bob@example.com>' <msg.txt subject body text Signed-off-by: Alice <alice@example.com> Signed-off-by: Bob <bob@example.com>
Use the --in-place option to edit a commit message file in place:
$ cat msg.txt subject body text Signed-off-by: Bob <bob@example.com> $ git interpret-trailers --trailer 'Acked-by: Alice <alice@example.com>' --in-place msg.txt $ cat msg.txt subject body text Signed-off-by: Bob <bob@example.com> Acked-by: Alice <alice@example.com>
Extract the last commit as a patch, and add a Cc and a Reviewed-by trailer to it:
$ git format-patch -1 0001-foo.patch $ git interpret-trailers --trailer 'Cc: Alice <alice@example.com>' --trailer 'Reviewed-by: Bob <bob@example.com>' 0001-foo.patch >0001-bar.patch
Configure a sign trailer with a command to automatically add a 'Signed-off-by: ' with the author information only if there is no 'Signed-off-by: ' already, and show how it works:
$ cat msg1.txt subject body text $ git config trailer.sign.key "Signed-off-by: " $ git config trailer.sign.ifmissing add $ git config trailer.sign.ifexists doNothing $ git config trailer.sign.cmd 'echo "$(git config user.name) <$(git config user.email)>"' $ git interpret-trailers --trailer sign <msg1.txt subject body text Signed-off-by: Bob <bob@example.com> $ cat msg2.txt subject body text Signed-off-by: Alice <alice@example.com> $ git interpret-trailers --trailer sign <msg2.txt subject body text Signed-off-by: Alice <alice@example.com>
Configure a fix trailer with a key that contains a # and no space after this character, and show how it works:
$ git config trailer.separators ":#" $ git config trailer.fix.key "Fix #" $ echo "subject" | git interpret-trailers --trailer fix=42 subject Fix #42
Configure a help trailer with a cmd use a script glog-find-author which search specified author identity from git log in git repository and show how it works:
$ cat ~/bin/glog-find-author #!/bin/sh test -n "$1" && git log --author="$1" --pretty="%an <%ae>" -1 || true $ cat msg.txt subject body text $ git config trailer.help.key "Helped-by: " $ git config trailer.help.ifExists "addIfDifferentNeighbor" $ git config trailer.help.cmd "~/bin/glog-find-author" $ git interpret-trailers --trailer="help:Junio" --trailer="help:Couder" <msg.txt subject body text Helped-by: Junio C Hamano <gitster@pobox.com> Helped-by: Christian Couder <christian.couder@gmail.com>
Configure a ref trailer with a cmd use a script glog-grep to grep last relevant commit from git log in the git repository and show how it works:
$ cat ~/bin/glog-grep #!/bin/sh test -n "$1" && git log --grep "$1" --pretty=reference -1 || true $ cat msg.txt subject body text $ git config trailer.ref.key "Reference-to: " $ git config trailer.ref.ifExists "replace" $ git config trailer.ref.cmd "~/bin/glog-grep" $ git interpret-trailers --trailer="ref:Add copyright notices." <msg.txt subject body text Reference-to: 8bc9a0c769 (Add copyright notices., 2005-04-07)
Configure a see trailer with a command to show the subject of a commit that is related, and show how it works:
$ cat msg.txt subject body text see: HEAD~2 $ cat ~/bin/glog-ref #!/bin/sh git log -1 --oneline --format="%h (%s)" --abbrev-commit --abbrev=14 $ git config trailer.see.key "See-also: " $ git config trailer.see.ifExists "replace" $ git config trailer.see.ifMissing "doNothing" $ git config trailer.see.cmd "glog-ref" $ git interpret-trailers --trailer=see <msg.txt subject body text See-also: fe3187489d69c4 (subject of related commit)
Configure a commit template with some trailers with empty values (using sed to show and keep the trailing spaces at the end of the trailers), then configure a commit-msg hook that uses git interpret-trailers to remove trailers with empty values and to add a git-version trailer:
$ cat temp.txt ***subject*** ***message*** Fixes: Z Cc: Z Reviewed-by: Z Signed-off-by: Z $ sed -e 's/ Z$/ /' temp.txt > commit_template.txt $ git config commit.template commit_template.txt $ cat .git/hooks/commit-msg #!/bin/sh git interpret-trailers --trim-empty --trailer "git-version: \$(git describe)" "\$1" > "\$1.new" mv "\$1.new" "\$1" $ chmod +x .git/hooks/commit-msg
the section called “git-commit(1)”, the section called “git-format-patch(1)”, the section called “git-config(1)”
Part of the the section called “git(1)” suite
Shows the commit logs.
List commits that are reachable by following the parent links from the given commit(s), but exclude commits that are reachable from the one(s) given with a ^ in front of them. The output is given in reverse chronological order by default.
You can think of this as a set operation. Commits reachable from any of the commits given on the command line form a set, and then commits reachable from any of the ones given with ^ in front are subtracted from that set. The remaining commits are what comes out in the command's output. Various other options and paths parameters can be used to further limit the result.
Thus, the following command:
$ git log foo bar ^baz
means "list all the commits which are reachable from foo or bar, but not from baz".
A special notation "<commit1>..<commit2>" can be used as a short-hand for "^<commit1> <commit2>". For example, either of the following may be used interchangeably:
$ git log origin..HEAD $ git log HEAD ^origin
Another special notation is "<commit1>…<commit2>" which is useful for merges. The resulting set of commits is the symmetric difference between the two operands. The following two commands are equivalent:
$ git log A B --not $(git merge-base --all A B) $ git log A...B
The command takes options applicable to the the section called “git-rev-list(1)” command to control what is shown and how, and options applicable to the the section called “git-diff(1)” command to control how the changes each commit introduces are shown.
For each candidate reference, do not use it for decoration if it matches any patterns given to --decorate-refs-exclude or if it doesn't match any of the patterns given to --decorate-refs. The log.excludeDecoration config option allows excluding refs from the decorations, but an explicit --decorate-refs pattern will override a match in log.excludeDecoration.
If none of these options or config settings are given, then references are used as decoration if they match HEAD, refs/heads/, refs/remotes/, refs/stash/, or refs/tags/.
Without this flag, git log -p <path>... shows commits that touch the specified paths, and diffs about the same specified paths. With this, the full diff is shown for commits that touch the specified paths; this means that "<path>…" limits only commits, and doesn't limit diff for those commits.
Note that this affects all diff-based output types, e.g. those produced by --stat, etc.
Trace the evolution of the line range given by <start>,<end>, or by the function name regex <funcname>, within the <file>. You may not give any pathspec limiters. This is currently limited to a walk starting from a single revision, i.e., you may only give zero or one positive revision arguments, and <start> and <end> (or <funcname>) must exist in the starting revision. You can specify this option more than once. Implies --patch. Patch output can be suppressed using --no-patch, but other diff formats (namely --raw, --numstat, --shortstat, --dirstat, --summary, --name-only, --name-status, --check) are not currently implemented.
<start> and <end> can take one of these forms:
number
If <start> or <end> is a number, it specifies an absolute line number (lines count from 1).
/regex/
This form will use the first line matching the given POSIX regex. If <start> is a regex, it will search from the end of the previous -L range, if any, otherwise from the start of file. If <start> is ^/regex/, it will search from the start of file. If <end> is a regex, it will search starting at the line given by <start>.
+offset or -offset
This is only valid for <end> and will specify a number of lines before or after the line given by <start>.
If :<funcname> is given in place of <start> and <end>, it is a regular expression that denotes the range from the first funcname line that matches <funcname>, up to the next funcname line. :<funcname> searches from the end of the previous -L range, if any, otherwise from the start of file. ^:<funcname> searches from the start of file. The function names are determined in the same way as git diff works out patch hunk headers (see Defining a custom hunk-header in the section called “gitattributes(5)”).
Show only commits that are enough to explain how the files that match the specified paths came to be. See History Simplification below for details and other simplification modes.
Paths may need to be prefixed with -- to separate them from options or the revision range, when confusion arises.
Besides specifying a range of commits that should be listed using the special notations explained in the description, additional commit limiting may be applied.
Using more options generally further limits the output (e.g. --since=<date1> limits to commits newer than <date1>, and using it with --grep=<pattern> further limits to commits whose log message has a line that matches <pattern>), unless otherwise noted.
Note that these are applied before commit ordering and formatting options, such as --reverse.
Limit the commits output to ones with a log message that matches the specified pattern (regular expression). With more than one --grep=<pattern>, commits whose message matches any of the given patterns are chosen (but see --all-match).
When --notes is in effect, the message from the notes is matched as if it were part of the log message.
Consider the limiting patterns to be Perl-compatible regular expressions.
Support for these types of regular expressions is an optional compile-time dependency. If Git wasn't compiled with support for them providing this option will cause it to die.
Show only commits which have at least (or at most) that many parent commits. In particular, --max-parents=1 is the same as --no-merges, --min-parents=2 is the same as --merges. --max-parents=0 gives all root commits and --min-parents=3 all octopus merges.
--no-min-parents and --no-max-parents reset these limits (to no limit) again. Equivalent forms are --min-parents=0 (any commit has 0 or more parents) and --max-parents=-1 (negative numbers denote no upper limit).
When finding commits to include, follow only the first parent commit upon seeing a merge commit. This option can give a better overview when viewing the evolution of a particular topic branch, because merges into a topic branch tend to be only about adjusting to updated upstream from time to time, and this option allows you to ignore the individual commits brought in to your history by such a merge.
This option also changes default diff format for merge commits to first-parent, see --diff-merges=first-parent for details.
Do not include refs matching <glob-pattern> that the next --all, --branches, --tags, --remotes, or --glob would otherwise consider. Repetitions of this option accumulate exclusion patterns up to the next --all, --branches, --tags, --remotes, or --glob option (other options or arguments do not clear accumulated patterns).
The patterns given should not begin with refs/heads, refs/tags, or refs/remotes when applied to --branches, --tags, or --remotes, respectively, and they must begin with refs/ when applied to --glob or --all. If a trailing /* is intended, it must be given explicitly.
Omit any commit that introduces the same change as another commit on the other side when the set of commits are limited with symmetric difference.
For example, if you have two branches, A and B, a usual way to list all commits on only one side of them is with --left-right (see the example below in the description of the --left-right option). However, it shows the commits that were cherry-picked from the other branch (for example, 3rd on b may be cherry-picked from branch A). With this option, such pairs of commits are excluded from the output.
List only commits on the respective side of a symmetric difference, i.e. only those which would be marked < resp. > by --left-right.
For example, --cherry-pick --right-only A...B omits those commits from B which are in A or are patch-equivalent to a commit in A. In other words, this lists the + commits from git cherry A B. More precisely, --cherry-pick --right-only --no-merges gives the exact list.
Instead of walking the commit ancestry chain, walk reflog entries from the most recent one to older ones. When this option is used you cannot specify commits to exclude (that is, ^commit, commit1..commit2, and commit1...commit2 notations cannot be used).
With --pretty format other than oneline and reference (for obvious reasons), this causes the output to have two extra lines of information taken from the reflog. The reflog designator in the output may be shown as ref@{<Nth>} (where <Nth> is the reverse-chronological index in the reflog) or as ref@{<timestamp>} (with the <timestamp> for that entry), depending on a few rules:
Under --pretty=oneline, the commit message is prefixed with this information on the same line. This option cannot be combined with --reverse. See also the section called “git-reflog(1)”.
Under --pretty=reference, this information will not be shown at all.
Sometimes you are only interested in parts of the history, for example the commits modifying a particular <path>. But there are two parts of History Simplification, one part is selecting the commits and the other is how to do it, as there are various strategies to simplify the history.
The following options select the commits to be shown:
Note that extra commits can be shown to give a meaningful history.
The following options affect the way the simplification is performed:
A more detailed explanation follows.
Suppose you specified foo as the <paths>. We shall call commits that modify foo !TREESAME, and the rest TREESAME. (In a diff filtered for foo, they look different and equal, respectively.)
In the following, we will always refer to the same example history to illustrate the differences between simplification settings. We assume that you are filtering for a file foo in this commit graph:
.-A---M---N---O---P---Q
/ / / / / /
I B C D E Y
\ / / / / /
`-------------' XThe horizontal line of history A---Q is taken to be the first parent of each merge. The commits are:
rev-list walks backwards through history, including or excluding commits based on whether --full-history and/or parent rewriting (via --parents or --children) are used. The following settings are available.
Commits are included if they are not TREESAME to any parent (though this can be changed, see --sparse below). If the commit was a merge, and it was TREESAME to one parent, follow only that parent. (Even if there are several TREESAME parents, follow only one of them.) Otherwise, follow all parents.
This results in:
.-A---N---O
/ / /
I---------DNote how the rule to only follow the TREESAME parent, if one is available, removed B from consideration entirely. C was considered via N, but is TREESAME. Root commits are compared to an empty tree, so I is !TREESAME.
Parent/child relations are only visible with --parents, but that does not affect the commits selected in default mode, so we have shown the parent lines.
This mode differs from the default in one point: always follow all parents of a merge, even if it is TREESAME to one of them. Even if more than one side of the merge has commits that are included, this does not imply that the merge itself is! In the example, we get
I A B N D O P Q
M was excluded because it is TREESAME to both parents. E, C and B were all walked, but only B was !TREESAME, so the others do not appear.
Note that without parent rewriting, it is not really possible to talk about the parent/child relationships between the commits, so we show them disconnected.
Ordinary commits are only included if they are !TREESAME (though this can be changed, see --sparse below).
Merges are always included. However, their parent list is rewritten: Along each parent, prune away commits that are not included themselves. This results in
.-A---M---N---O---P---Q
/ / / / /
I B / D /
\ / / / /
`-------------'Compare to --full-history without rewriting above. Note that E was pruned away because it is TREESAME, but the parent list of P was rewritten to contain E's parent I. The same happened for C and N, and X, Y and Q.
In addition to the above settings, you can change whether TREESAME affects inclusion:
All commits that are walked are included.
Note that without --full-history, this still simplifies merges: if one of the parents is TREESAME, we follow only that one, so the other sides of the merge are never walked.
First, build a history graph in the same way that --full-history with parent rewriting does (see above).
Then simplify each commit C to its replacement C' in the final history according to the following rules:
The effect of this is best shown by way of comparing to --full-history with parent rewriting. The example turns into:
.-A---M---N---O
/ / /
I B D
\ / /
`---------'Note the major differences in N, P, and Q over --full-history:
There is another simplification mode available:
Limit the displayed commits to those which are an ancestor of <commit>, or which are a descendant of <commit>, or are <commit> itself.
As an example use case, consider the following commit history:
D---E-------F
/ \ \
B---C---G---H---I---J
/ \
A-------K---------------L--MA regular D..M computes the set of commits that are ancestors of M, but excludes the ones that are ancestors of D. This is useful to see what happened to the history leading to M since D, in the sense that what does M have that did not exist in D. The result in this example would be all the commits, except A and B (and D itself, of course).
When we want to find out what commits in M are contaminated with the bug introduced by D and need fixing, however, we might want to view only the subset of D..M that are actually descendants of D, i.e. excluding C and K. This is exactly what the --ancestry-path option does. Applied to the D..M range, it results in:
E-------F
\ \
G---H---I---J
\
L--MWe can also use --ancestry-path=D instead of --ancestry-path which means the same thing when applied to the D..M range but is just more explicit.
If we instead are interested in a given topic within this range, and all commits affected by that topic, we may only want to view the subset of D..M which contain that topic in their ancestry path. So, using --ancestry-path=H D..M for example would result in:
E
\
C---G---H---I---J
\
L--MWhereas --ancestry-path=K D..M would result in
K---------------L--M
Before discussing another option, --show-pulls, we need to create a new example history.
A common problem users face when looking at simplified history is that a commit they know changed a file somehow does not appear in the file's simplified history. Let's demonstrate a new example and show how options such as --full-history and --simplify-merges works in that case:
.-A---M-----C--N---O---P
/ / \ \ \/ / /
I B \ R-'`-Z' /
\ / \/ /
\ / /\ /
`---X--' `---Y--'For this example, suppose I created file.txt which was modified by A, B, and X in different ways. The single-parent commits C, Z, and Y do not change file.txt. The merge commit M was created by resolving the merge conflict to include both changes from A and B and hence is not TREESAME to either. The merge commit R, however, was created by ignoring the contents of file.txt at M and taking only the contents of file.txt at X. Hence, R is TREESAME to X but not M. Finally, the natural merge resolution to create N is to take the contents of file.txt at R, so N is TREESAME to R but not C. The merge commits O and P are TREESAME to their first parents, but not to their second parents, Z and Y respectively.
When using the default mode, N and R both have a TREESAME parent, so those edges are walked and the others are ignored. The resulting history graph is:
I---X
When using --full-history, Git walks every edge. This will discover the commits A and B and the merge M, but also will reveal the merge commits O and P. With parent rewriting, the resulting graph is:
.-A---M--------N---O---P
/ / \ \ \/ / /
I B \ R-'`--' /
\ / \/ /
\ / /\ /
`---X--' `------'Here, the merge commits O and P contribute extra noise, as they did not actually contribute a change to file.txt. They only merged a topic that was based on an older version of file.txt. This is a common issue in repositories using a workflow where many contributors work in parallel and merge their topic branches along a single trunk: many unrelated merges appear in the --full-history results.
When using the --simplify-merges option, the commits O and P disappear from the results. This is because the rewritten second parents of O and P are reachable from their first parents. Those edges are removed and then the commits look like single-parent commits that are TREESAME to their parent. This also happens to the commit N, resulting in a history view as follows:
.-A---M--.
/ / \
I B R
\ / /
\ / /
`---X--'In this view, we see all of the important single-parent changes from A, B, and X. We also see the carefully-resolved merge M and the not-so-carefully-resolved merge R. This is usually enough information to determine why the commits A and B "disappeared" from history in the default view. However, there are a few issues with this approach.
The first issue is performance. Unlike any previous option, the --simplify-merges option requires walking the entire commit history before returning a single result. This can make the option difficult to use for very large repositories.
The second issue is one of auditing. When many contributors are working on the same repository, it is important which merge commits introduced a change into an important branch. The problematic merge R above is not likely to be the merge commit that was used to merge into an important branch. Instead, the merge N was used to merge R and X into the important branch. This commit may have information about why the change X came to override the changes from A and B in its commit message.
In addition to the commits shown in the default history, show each merge commit that is not TREESAME to its first parent but is TREESAME to a later parent.
When a merge commit is included by --show-pulls, the merge is treated as if it "pulled" the change from another branch. When using --show-pulls on this example (and no other options) the resulting graph is:
I---X---R---N
Here, the merge commits R and N are included because they pulled the commits X and R into the base branch, respectively. These merges are the reason the commits A and B do not appear in the default history.
When --show-pulls is paired with --simplify-merges, the graph includes all of the necessary information:
.-A---M--. N
/ / \ /
I B R
\ / /
\ / /
`---X--'Notice that since M is reachable from R, the edge from N to M was simplified away. However, N still appears in the history as an important commit because it "pulled" the change R into the main branch.
The --simplify-by-decoration option allows you to view only the big picture of the topology of the history, by omitting commits that are not referenced by tags. Commits are marked as !TREESAME (in other words, kept after history simplification rules described above) if (1) they are referenced by tags, or (2) they change the contents of the paths given on the command line. All other commits are marked as TREESAME (subject to be simplified away).
By default, the commits are shown in reverse chronological order.
Show no parents before all of its children are shown, and avoid showing commits on multiple lines of history intermixed.
For example, in a commit history like this:
---1----2----4----7
\ \
3----5----6----8---where the numbers denote the order of commit timestamps, git rev-list and friends with --date-order show the commits in the timestamp order: 8 7 6 5 4 3 2 1.
With --topo-order, they would show 8 6 5 3 7 4 2 1 (or 8 7 4 2 6 5 3 1); some older commits are shown before newer ones in order to avoid showing the commits from two parallel development track mixed together.
These options are mostly targeted for packing of Git repositories.
Pretty-print the contents of the commit logs in a given format, where <format> can be one of oneline, short, medium, full, fuller, reference, email, raw, format:<string> and tformat:<string>. When <format> is none of the above, and has %placeholder in it, it acts as if --pretty=tformat:<format> were given.
See the "PRETTY FORMATS" section for some additional details for each format. When =<format> part is omitted, it defaults to medium.
Note: you can specify the default pretty format in the repository configuration (see the section called “git-config(1)”).
Instead of showing the full 40-byte hexadecimal commit object name, show a prefix that names the object uniquely. "--abbrev=<n>" (which also modifies diff output, if it is displayed) option can be used to specify the minimum length of the prefix.
This should make "--pretty=oneline" a whole lot more readable for people using 80-column terminals.
Perform a tab expansion (replace each tab with enough spaces to fill to the next display column that is a multiple of <n>) in the log message before showing it in the output. --expand-tabs is a short-hand for --expand-tabs=8, and --no-expand-tabs is a short-hand for --expand-tabs=0, which disables tab expansion.
By default, tabs are expanded in pretty formats that indent the log message by 4 spaces (i.e. medium, which is the default, full, and fuller).
Show the notes (see the section called “git-notes(1)”) that annotate the commit, when showing the commit log message. This is the default for git log, git show and git whatchanged commands when there is no --pretty, --format, or --oneline option given on the command line.
By default, the notes shown are from the notes refs listed in the core.notesRef and notes.displayRef variables (or corresponding environment overrides). See the section called “git-config(1)” for more details.
With an optional <ref> argument, use the ref to find the notes to display. The ref can specify the full refname when it begins with refs/notes/; when it begins with notes/, refs/ and otherwise refs/notes/ is prefixed to form the full name of the ref.
Multiple --notes options can be combined to control which notes are being displayed. Examples: "--notes=foo" will show only notes from "refs/notes/foo"; "--notes=foo --notes" will show both notes from "refs/notes/foo" and from the default notes ref(s).
Only takes effect for dates shown in human-readable format, such as when using --pretty. log.date config variable sets a default value for the log command's --date option. By default, dates are shown in the original time zone (either committer's or author's). If -local is appended to the format (e.g., iso-local), the user's local time zone is used instead.
--date=relative shows dates relative to the current time, e.g. 2 hours ago. The -local option has no effect for --date=relative.
--date=local is an alias for --date=default-local.
--date=iso (or --date=iso8601) shows timestamps in a ISO 8601-like format. The differences to the strict ISO 8601 format are:
--date=iso-strict (or --date=iso8601-strict) shows timestamps in strict ISO 8601 format.
--date=rfc (or --date=rfc2822) shows timestamps in RFC 2822 format, often found in email messages.
--date=short shows only the date, but not the time, in YYYY-MM-DD format.
--date=raw shows the date as seconds since the epoch (1970-01-01 00:00:00 UTC), followed by a space, and then the timezone as an offset from UTC (a + or - with four digits; the first two are hours, and the second two are minutes). I.e., as if the timestamp were formatted with strftime("%s %z")). Note that the -local option does not affect the seconds-since-epoch value (which is always measured in UTC), but does switch the accompanying timezone value.
--date=human shows the timezone if the timezone does not match the current time-zone, and doesn't print the whole date if that matches (ie skip printing year for dates that are "this year", but also skip the whole date itself if it's in the last few days and we can just say what weekday it was). For older dates the hour and minute is also omitted.
--date=unix shows the date as a Unix epoch timestamp (seconds since 1970). As with --raw, this is always in UTC and therefore -local has no effect.
--date=format:... feeds the format ... to your system strftime, except for %s, %z, and %Z, which are handled internally. Use --date=format:%c to show the date in your system locale's preferred format. See the strftime manual for a complete list of format placeholders. When using -local, the correct syntax is --date=format-local:....
--date=default is the default format, and is based on ctime(3) output. It shows a single line with three-letter day of the week, three-letter month, day-of-month, hour-minute-seconds in "HH:MM:SS" format, followed by 4-digit year, plus timezone information, unless the local time zone is used, e.g. Thu Jan 1 00:00:00 1970 +0000.
Mark which side of a symmetric difference a commit is reachable from. Commits from the left side are prefixed with < and those from the right with >. If combined with --boundary, those commits are prefixed with -.
For example, if you have this topology:
y---b---b branch B
/ \ /
/ .
/ / \
o---x---a---a branch Ayou would get an output like this:
$ git rev-list --left-right --boundary --pretty=oneline A...B
>bbbbbbb... 3rd on b
>bbbbbbb... 2nd on b
<aaaaaaa... 3rd on a
<aaaaaaa... 2nd on a
-yyyyyyy... 1st on b
-xxxxxxx... 1st on aDraw a text-based graphical representation of the commit history on the left hand side of the output. This may cause extra lines to be printed in between commits, in order for the graph history to be drawn properly. Cannot be combined with --no-walk.
This enables parent rewriting, see History Simplification above.
This implies the --topo-order option by default, but the --date-order option may also be specified.
If the commit is a merge, and if the pretty-format is not oneline, email or raw, an additional line is inserted before the Author: line. This line begins with "Merge: " and the hashes of ancestral commits are printed, separated by spaces. Note that the listed commits may not necessarily be the list of the direct parent commits if you have limited your view of history: for example, if you are only interested in changes related to a certain directory or file.
There are several built-in formats, and you can define additional formats by setting a pretty.<name> config option to either another format name, or a format: string, as described below (see the section called “git-config(1)”). Here are the details of the built-in formats:
oneline
<hash> <title-line>
This is designed to be as compact as possible.
short
commit <hash> Author: <author>
<title-line>
medium
commit <hash> Author: <author> Date: <author-date>
<title-line>
<full-commit-message>
full
commit <hash> Author: <author> Commit: <committer>
<title-line>
<full-commit-message>
fuller
commit <hash> Author: <author> AuthorDate: <author-date> Commit: <committer> CommitDate: <committer-date>
<title-line>
<full-commit-message>
reference
<abbrev-hash> (<title-line>, <short-author-date>)
This format is used to refer to another commit in a commit message and is the same as --pretty='format:%C(auto)%h (%s, %ad)'. By default, the date is formatted with --date=short unless another --date option is explicitly specified. As with any format: with format placeholders, its output is not affected by other options like --decorate and --walk-reflogs.
From <hash> <date> From: <author> Date: <author-date> Subject: [PATCH] <title-line>
<full-commit-message>
mboxrd
Like email, but lines in the commit message starting with "From " (preceded by zero or more ">") are quoted with ">" so they aren't confused as starting a new commit.
raw
The raw format shows the entire commit exactly as stored in the commit object. Notably, the hashes are displayed in full, regardless of whether --abbrev or --no-abbrev are used, and parents information show the true parent commits, without taking grafts or history simplification into account. Note that this format affects the way commits are displayed, but not the way the diff is shown e.g. with git log --raw. To get full object names in a raw diff format, use --no-abbrev.
format:<format-string>
The format:<format-string> format allows you to specify which information you want to show. It works a little bit like printf format, with the notable exception that you get a newline with %n instead of \n.
E.g, format:"The author of %h was %an, %ar%nThe title was >>%s<<%n" would show something like this:
The author of fe6e0ee was Junio C Hamano, 23 hours ago The title was >>t4119: test autocomputing -p<n> for traditional diff input.<<
The placeholders are:
Placeholders that expand to a single literal character:
Placeholders that affect formatting of later placeholders:
Placeholders that expand to information extracted from the commit:
ref names with custom decorations. The decorate string may be followed by a colon and zero or more comma-separated options. Option values may contain literal formatting codes. These must be used for commas (%x2C) and closing parentheses (%x29), due to their role in the option syntax.
For example, to produce decorations with no wrapping or tag annotations, and spaces as separators:
%(decorate:prefix=,suffix=,tag=,separator= )
human-readable name, like the section called “git-describe(1)”; empty string for undescribable commits. The describe string may be followed by a colon and zero or more comma-separated options. Descriptions can be inconsistent when tags are added or removed at the same time.
display the trailers of the body as interpreted by the section called “git-interpret-trailers(1)”. The trailers string may be followed by a colon and zero or more comma-separated options. If any option is provided multiple times, the last occurrence wins.
Some placeholders may depend on other options given to the revision traversal engine. For example, the %g* reflog options will insert an empty string unless we are traversing reflog entries (e.g., by git log -g). The %d and %D placeholders will use the "short" decoration format if --decorate was not already provided on the command line.
The boolean options accept an optional value [=<bool-value>]. The values taken by --type=bool git-config[1], like yes and off, are all accepted. Giving a boolean option without =<value> is equivalent to giving it with =true.
If you add a + (plus sign) after % of a placeholder, a line-feed is inserted immediately before the expansion if and only if the placeholder expands to a non-empty string.
If you add a - (minus sign) after % of a placeholder, all consecutive line-feeds immediately preceding the expansion are deleted if and only if the placeholder expands to an empty string.
If you add a ` ` (space) after % of a placeholder, a space is inserted immediately before the expansion if and only if the placeholder expands to a non-empty string.
tformat:
The tformat: format works exactly like format:, except that it provides "terminator" semantics instead of "separator" semantics. In other words, each commit has the message terminator character (usually a newline) appended, rather than a separator placed between entries. This means that the final entry of a single-line format will be properly terminated with a new line, just as the "oneline" format does. For example:
$ git log -2 --pretty=format:%h 4da45bef \ | perl -pe '$_ .= " -- NO NEWLINE\n" unless /\n/' 4da45be 7134973 -- NO NEWLINE $ git log -2 --pretty=tformat:%h 4da45bef \ | perl -pe '$_ .= " -- NO NEWLINE\n" unless /\n/' 4da45be 7134973
In addition, any unrecognized string that has a % in it is interpreted as if it has tformat: in front of it. For example, these two are equivalent:
$ git log -2 --pretty=tformat:%h 4da45bef $ git log -2 --pretty=%h 4da45bef
By default, git log does not generate any diff output. The options below can be used to show the changes made by each commit.
Note that unless one of --diff-merges variants (including short -m, -c, --cc, and --dd options) is explicitly given, merge commits will not show a diff, even if a diff format like --patch is selected, nor will they match search options like -S. The exception is when --first-parent is in use, in which case first-parent is the default format for merge commits.
Specify diff format to be used for merge commits. Default is off unless --first-parent is in use, in which case first-parent is the default.
The following formats are supported:
Remerge two-parent merge commits to create a temporary tree object--potentially containing files with conflict markers and such. A diff is then shown between that temporary tree and the actual merge commit.
The output emitted when this option is used is subject to change, and so is its interaction with other options (unless explicitly documented).
Generate a diff using the "anchored diff" algorithm.
This option may be specified more than once.
If a line exists in both the source and destination, exists only once, and starts with <text>, this algorithm attempts to prevent it from appearing as a deletion or addition in the output. It uses the "patience diff" algorithm internally.
Choose a diff algorithm. The variants are as follows:
For instance, if you configured the diff.algorithm variable to a non-default value and want to use the default one, then you have to use --diff-algorithm=default option.
Generate a diffstat. By default, as much space as necessary will be used for the filename part, and the rest for the graph part. Maximum width defaults to terminal width, or 80 columns if not connected to a terminal, and can be overridden by <width>. The width of the filename part can be limited by giving another width <name-width> after a comma or by setting diff.statNameWidth=<name-width>. The width of the graph part can be limited by using --stat-graph-width=<graph-width> or by setting diff.statGraphWidth=<graph-width>. Using --stat or --stat-graph-width affects all commands generating a stat graph, while setting diff.statNameWidth or diff.statGraphWidth does not affect git format-patch. By giving a third parameter <count>, you can limit the output to the first <count> lines, followed by ... if there are more.
These parameters can also be set individually with --stat-width=<width>, --stat-name-width=<name-width> and --stat-count=<count>.
Output the distribution of relative amount of changes for each sub-directory. The behavior of --dirstat can be customized by passing it a comma separated list of parameters. The defaults are controlled by the diff.dirstat configuration variable (see the section called “git-config(1)”). The following parameters are available:
Example: The following will count changed files, while ignoring directories with less than 10% of the total amount of changed files, and accumulating child directory counts in the parent directories: --dirstat=files,10,cumulative.
Separate the commits with NULs instead of newlines.
Also, when --raw or --numstat has been given, do not munge pathnames and use NULs as output field terminators.
Without this option, pathnames with "unusual" characters are quoted as explained for the configuration variable core.quotePath (see the section called “git-config(1)”).
Moved lines of code are colored differently. The <mode> defaults to no if the option is not given and to zebra if the option with no mode is given. The mode must be one of:
This configures how whitespace is ignored when performing the move detection for --color-moved. These modes can be given as a comma separated list:
By default, words are delimited by whitespace; see --word-diff-regex below. The <mode> defaults to plain, and must be one of:
[-removed-] and {added}. Makes no
attempts to escape the delimiters if they appear in the input,
so the output may be ambiguous.
Note that despite the name of the first mode, color is used to highlight the changed parts in all modes if enabled.
Use <regex> to decide what a word is, instead of considering runs of non-whitespace to be a word. Also implies --word-diff unless it was already enabled.
Every non-overlapping match of the <regex> is considered a word. Anything between these matches is considered whitespace and ignored(!) for the purposes of finding differences. You may want to append |[^[:space:]] to your regular expression to make sure that it matches all non-whitespace characters. A match that contains a newline is silently truncated(!) at the newline.
For example, --word-diff-regex=. will treat each character as a word and, correspondingly, show differences character by character.
The regex can also be set via a diff driver or configuration option, see the section called “gitattributes(5)” or the section called “git-config(1)”. Giving it explicitly overrides any diff driver or configuration setting. Diff drivers override configuration settings.
Break complete rewrite changes into pairs of delete and create. This serves two purposes:
It affects the way a change that amounts to a total rewrite of a file not as a series of deletion and insertion mixed together with a very few lines that happen to match textually as the context, but as a single deletion of everything old followed by a single insertion of everything new, and the number <m> controls this aspect of the -B option (defaults to 60%). -B/70% specifies that less than 30% of the original should remain in the result for Git to consider it a total rewrite (i.e. otherwise the resulting patch will be a series of deletion and insertion mixed together with context lines).
When used with -M, a totally-rewritten file is also considered as the source of a rename (usually -M only considers a file that disappeared as the source of a rename), and the number <n> controls this aspect of the -B option (defaults to 50%). -B20% specifies that a change with addition and deletion compared to 20% or more of the file's size are eligible for being picked up as a possible source of a rename to another file.
Omit the preimage for deletes, i.e. print only the header but not the diff between the preimage and /dev/null. The resulting patch is not meant to be applied with patch or git apply; this is solely for people who want to just concentrate on reviewing the text after the change. In addition, the output obviously lacks enough information to apply such a patch in reverse, even manually, hence the name of the option.
When used together with -B, omit also the preimage in the deletion part of a delete/create pair.
Select only files that are Added (A), Copied (C), Deleted (D), Modified (M), Renamed (R), have their type (i.e. regular file, symlink, submodule, …) changed (T), are Unmerged (U), are Unknown (X), or have had their pairing Broken (B). Any combination of the filter characters (including none) can be used. When * (All-or-none) is added to the combination, all paths are selected if there is any file that matches other criteria in the comparison; if there is no file that matches other criteria, nothing is selected.
Also, these upper-case letters can be downcased to exclude. E.g. --diff-filter=ad excludes added and deleted paths.
Note that not all diffs can feature all types. For instance, copied and renamed entries cannot appear if detection for those types is disabled.
Look for differences that change the number of occurrences of the specified <string> (i.e. addition/deletion) in a file. Intended for the scripter's use.
It is useful when you're looking for an exact block of code (like a struct), and want to know the history of that block since it first came into being: use the feature iteratively to feed the interesting block in the preimage back into -S, and keep going until you get the very first version of the block.
Binary files are searched as well.
Look for differences whose patch text contains added/removed lines that match <regex>.
To illustrate the difference between -S<regex> --pickaxe-regex and -G<regex>, consider a commit with the following diff in the same file:
+ return frotz(nitfol, two->ptr, 1, 0); ... - hit = frotz(nitfol, mf2.ptr, 1, 0);
While git log -G"frotz\(nitfol" will show this commit, git log -S"frotz\(nitfol" --pickaxe-regex will not (because the number of occurrences of that string did not change).
Unless --text is supplied patches of binary files without a textconv filter will be ignored.
See the pickaxe entry in the section called “gitdiffcore(7)” for more information.
Look for differences that change the number of occurrences of the specified object. Similar to -S, just the argument is different in that it doesn't search for a specific string but for a specific object id.
The object can be a blob or a submodule commit. It implies the -t option in git-log to also find trees.
Control the order in which files appear in the output. This overrides the diff.orderFile configuration variable (see the section called “git-config(1)”). To cancel diff.orderFile, use -O/dev/null.
The output order is determined by the order of glob patterns in <orderfile>. All files with pathnames that match the first pattern are output first, all files with pathnames that match the second pattern (but not the first) are output next, and so on. All files with pathnames that do not match any pattern are output last, as if there was an implicit match-all pattern at the end of the file. If multiple pathnames have the same rank (they match the same pattern but no earlier patterns), their output order relative to each other is the normal order.
<orderfile> is parsed as follows:
Patterns have the same syntax and semantics as patterns used for fnmatch(3) without the FNM_PATHNAME flag, except a pathname also matches a pattern if removing any number of the final pathname components matches the pattern. For example, the pattern "foo*bar" matches "fooasdfbar" and "foo/bar/baz/asdf" but not "foobarx".
For more detailed explanation on these common options, see also the section called “gitdiffcore(7)”.
Running the section called “git-diff(1)”, the section called “git-log(1)”, the section called “git-show(1)”, the section called “git-diff-index(1)”, the section called “git-diff-tree(1)”, or the section called “git-diff-files(1)” with the -p option produces patch text. You can customize the creation of patch text via the GIT_EXTERNAL_DIFF and the GIT_DIFF_OPTS environment variables (see the section called “git(1)”), and the diff attribute (see the section called “gitattributes(5)”).
What the -p option produces is slightly different from the traditional diff format:
It is preceded by a "git diff" header that looks like this:
diff --git a/file1 b/file2
The a/ and b/ filenames are the same unless rename/copy is involved. Especially, even for a creation or a deletion, /dev/null is not used in place of the a/ or b/ filenames.
When a rename/copy is involved, file1 and file2 show the name of the source file of the rename/copy and the name of the file that the rename/copy produces, respectively.
It is followed by one or more extended header lines:
oldmode<mode>
newmode<mode>
deletedfilemode<mode>
newfilemode<mode>
copyfrom<path>
copyto<path>
renamefrom<path>
renameto<path>
similarityindex<number>
dissimilarityindex<number>
index<hash>..<hash> <mode>
File modes <mode> are printed as 6-digit octal numbers including the file type and file permission bits.
Path names in extended headers do not include the a/ and b/ prefixes.
The similarity index is the percentage of unchanged lines, and the dissimilarity index is the percentage of changed lines. It is a rounded down integer, followed by a percent sign. The similarity index value of 100% is thus reserved for two equal files, while 100% dissimilarity means that no line from the old file made it into the new one.
The index line includes the blob object names before and after the change. The <mode> is included if the file mode does not change; otherwise, separate lines indicate the old and the new mode.
All the file1 files in the output refer to files before the commit, and all the file2 files refer to files after the commit. It is incorrect to apply each change to each file sequentially. For example, this patch will swap a and b:
diff --git a/a b/b rename from a rename to b diff --git a/b b/a rename from b rename to a
Any diff-generating command can take the -c or --cc option to produce a combined diff when showing a merge. This is the default format when showing merges with the section called “git-diff(1)” or the section called “git-show(1)”. Note also that you can give suitable --diff-merges option to any of these commands to force generation of diffs in a specific format.
A "combined diff" format looks like this:
diff --combined describe.c
index fabadb8,cc95eb0..4866510
--- a/describe.c
+++ b/describe.c
@@@ -98,20 -98,12 +98,20 @@@
return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1;
}
- static void describe(char *arg)
-static void describe(struct commit *cmit, int last_one)
++static void describe(char *arg, int last_one)
{
+ unsigned char sha1[20];
+ struct commit *cmit;
struct commit_list *list;
static int initialized = 0;
struct commit_name *n;
+ if (get_sha1(arg, sha1) < 0)
+ usage(describe_usage);
+ cmit = lookup_commit_reference(sha1);
+ if (!cmit)
+ usage(describe_usage);
+
if (!initialized) {
initialized = 1;
for_each_ref(get_name);It is preceded by a "git diff" header, that looks like this (when the -c option is used):
diff --combined file
or like this (when the --cc option is used):
diff --cc file
It is followed by one or more extended header lines (this example shows a merge with two parents):
index<hash>,<hash>..<hash>
mode<mode>,<mode>..<mode>
newfilemode<mode>
deletedfilemode<mode>,<mode>
The mode <mode>,<mode>..<mode> line appears only if at least one of the <mode> is different from the rest. Extended headers with information about detected content movement (renames and copying detection) are designed to work with the diff of two <tree-ish> and are not used by combined diff format.
It is followed by a two-line from-file/to-file header:
--- a/file +++ b/file
Similar to the two-line header for the traditional unified diff format, /dev/null is used to signal created or deleted files.
However, if the --combined-all-paths option is provided, instead of a two-line from-file/to-file, you get an N+1 line from-file/to-file header, where N is the number of parents in the merge commit:
--- a/file --- a/file --- a/file +++ b/file
This extended format can be useful if rename or copy detection is active, to allow you to see the original name of the file in different parents.
Chunk header format is modified to prevent people from accidentally feeding it to patch -p1. Combined diff format was created for review of merge commit changes, and was not meant to be applied. The change is similar to the change in the extended index header:
@@@ <from-file-range> <from-file-range> <to-file-range> @@@
There are (number of parents + 1) @ characters in the chunk header for combined diff format.
Unlike the traditional unified diff format, which shows two files A and B with a single column that has - (minus -- appears in A but removed in B), + (plus -- missing in A but added to B), or " " (space -- unchanged) prefix, this format compares two or more files file1, file2,… with one file X, and shows how X differs from each of fileN. One column for each of fileN is prepended to the output line to note how X's line is different from it.
A - character in the column N means that the line appears in fileN but it does not appear in the result. A + character in the column N means that the line appears in the result, and fileN does not have that line (in other words, the line was added, from the point of view of that parent).
In the above example output, the function signature was changed from both files (hence two - removals from both file1 and file2, plus ++ to mean one line that was added does not appear in either file1 or file2). Also, eight other lines are the same from file1 but do not appear in file2 (hence prefixed with +).
When shown by git diff-tree -c, it compares the parents of a merge commit with the merge result (i.e. file1..fileN are the parents). When shown by git diff-files -c, it compares the two unresolved merge parents with the working tree file (i.e. file1 is stage 2 aka "our version", file2 is stage 3 aka "their version").
Git is to some extent character encoding agnostic.
Path names are encoded in UTF-8 normalization form C. This applies to tree objects, the index file, ref names, as well as path names in command line arguments, environment variables and config files (.git/config (see the section called “git-config(1)”), the section called “gitignore(5)”, the section called “gitattributes(5)” and the section called “gitmodules(5)”).
Note that Git at the core level treats path names simply as sequences of non-NUL bytes, there are no path name encoding conversions (except on Mac and Windows). Therefore, using non-ASCII path names will mostly work even on platforms and file systems that use legacy extended ASCII encodings. However, repositories created on such systems will not work properly on UTF-8-based systems (e.g. Linux, Mac, Windows) and vice versa. Additionally, many Git-based tools simply assume path names to be UTF-8 and will fail to display other encodings correctly.
Although we encourage that the commit log messages are encoded in UTF-8, both the core and Git Porcelain are designed not to force UTF-8 on projects. If all participants of a particular project find it more convenient to use legacy encodings, Git does not forbid it. However, there are a few things to keep in mind.
git commit and git commit-tree issue a warning if the commit log message given to it does not look like a valid UTF-8 string, unless you explicitly say your project uses a legacy encoding. The way to say this is to have i18n.commitEncoding in .git/config file, like this:
[i18n]
commitEncoding = ISO-8859-1Commit objects created with the above setting record the value of i18n.commitEncoding in their encoding header. This is to help other people who look at them later. Lack of this header implies that the commit log message is encoded in UTF-8.
git log, git show, git blame and friends look at the encoding header of a commit object, and try to re-code the log message into UTF-8 unless otherwise specified. You can specify the desired output encoding with i18n.logOutputEncoding in .git/config file, like this:
[i18n]
logOutputEncoding = ISO-8859-1If you do not have this configuration variable, the value of i18n.commitEncoding is used instead.
Note that we deliberately chose not to re-code the commit log message when a commit is made to force UTF-8 at the commit object level, because re-coding to UTF-8 is not necessarily a reversible operation.
See the section called “git-config(1)” for core variables and the section called “git-diff(1)” for settings related to diff generation.
Everything above this line in this section isn't included from the the section called “git-config(1)” documentation. The content that follows is the same as what's found there:
Set the default date-time mode for the log command. Setting a value for log.date is similar to using git log's --date option. See the section called “git-log(1)” for details.
If the format is set to "auto:foo" and the pager is in use, format "foo" will be used for the date format. Otherwise, "default" will be used.
Which merge strategy to choose by default when resolving notes conflicts. Must be one of manual, ours, theirs, union, or cat_sort_uniq. Defaults to manual. See the "NOTES MERGE STRATEGIES" section of the section called “git-notes(1)” for more information on each strategy.
This setting can be overridden by passing the --strategy option to the section called “git-notes(1)”.
Which ref (or refs, if a glob or specified more than once), in addition to the default set by core.notesRef or GIT_NOTES_REF, to read notes from when showing commit messages with the git log family of commands.
This setting can be overridden with the GIT_NOTES_DISPLAY_REF environment variable, which must be a colon separated list of refs or globs.
A warning will be issued for refs that do not exist, but a glob that does not match any refs is silently ignored.
This setting can be disabled by the --no-notes option to the the section called “git-log(1)” family of commands, or by the --notes=<ref> option accepted by those commands.
The effective value of core.notesRef (possibly overridden by GIT_NOTES_REF) is also implicitly added to the list of refs to be displayed.
When rewriting commits with <command> (currently amend or rebase), if this variable is false, git will not copy notes from the original to the rewritten commit. Defaults to true. See also notes.rewriteRef below.
This setting can be overridden with the GIT_NOTES_REWRITE_REF environment variable, which must be a colon separated list of refs or globs.
When copying notes during a rewrite (see the notes.rewrite.<command> option), determines what to do if the target commit already has a note. Must be one of overwrite, concatenate, cat_sort_uniq, or ignore. Defaults to concatenate.
This setting can be overridden with the GIT_NOTES_REWRITE_MODE environment variable.
When copying notes during a rewrite, specifies the (fully qualified) ref whose notes should be copied. May be a glob, in which case notes in all matching refs will be copied. You may also specify this configuration several times.
Does not have a default value; you must configure this variable to enable note rewriting. Set it to refs/notes/commits to enable rewriting for the default commit notes.
Can be overridden with the GIT_NOTES_REWRITE_REF environment variable. See notes.rewrite.<command> above for a further description of its format.
Part of the the section called “git(1)” suite
git ls-files [-z] [-t] [-v] [-f]
[-c|--cached] [-d|--deleted] [-o|--others] [-i|--ignored]
[-s|--stage] [-u|--unmerged] [-k|--killed] [-m|--modified]
[--resolve-undo]
[--directory [--no-empty-directory]] [--eol]
[--deduplicate]
[-x <pattern>|--exclude=<pattern>]
[-X <file>|--exclude-from=<file>]
[--exclude-per-directory=<file>]
[--exclude-standard]
[--error-unmatch] [--with-tree=<tree-ish>]
[--full-name] [--recurse-submodules]
[--abbrev[=<n>]] [--format=<format>] [--] [<file>…]
This command merges the file listing in the index with the actual working directory list, and shows different combinations of the two.
Several flags can be used to determine which files are shown, and each file may be printed multiple times if there are multiple entries in the index or if multiple statuses are applicable for the relevant file selection options.
Show status tags together with filenames. Note that for scripting purposes, the section called “git-status(1)” --porcelain and the section called “git-diff-files(1)” --name-status are almost always superior alternatives; users should look at the section called “git-status(1)” --short or the section called “git-diff(1)” --name-status for more user-friendly alternatives.
This option provides a reason for showing each filename, in the form of a status tag (which is followed by a space and then the filename). The status tags are all single characters from the following list:
Show <eolinfo> and <eolattr> of files. <eolinfo> is the file content identification used by Git when the "text" attribute is "auto" (or not set and core.autocrlf is not false). <eolinfo> is either "-text", "none", "lf", "crlf", "mixed" or "".
"" means the file is not a regular file, it is not in the index or not accessible in the working tree.
<eolattr> is the attribute that is used when checking out or committing, it is either "", "-text", "text", "text=auto", "text eol=lf", "text eol=crlf". Since Git 2.10 "text=auto eol=lf" and "text=auto eol=crlf" are supported.
Both the <eolinfo> in the index ("i/<eolinfo>") and in the working tree ("w/<eolinfo>") are shown for regular files, followed by the ("attr/<eolattr>").
git ls-files just outputs the filenames unless --stage is specified in which case it outputs:
[<tag> ]<mode> <object> <stage> <file>
git ls-files --eol will show i/<eolinfo><SPACES>w/<eolinfo><SPACES>attr/<eolattr><SPACE*><TAB><file>
git ls-files --unmerged and git ls-files --stage can be used to examine detailed information on unmerged paths.
For an unmerged path, instead of recording a single mode/SHA-1 pair, the index records up to three such pairs; one from tree O in stage 1, A in stage 2, and B in stage 3. This information can be used by the user (or the porcelain) to see what should eventually be recorded at the path. (see the section called “git-read-tree(1)” for more information on state)
Without the -z option, pathnames with "unusual" characters are quoted as explained for the configuration variable core.quotePath (see the section called “git-config(1)”). Using -z the filename is output verbatim and the line is terminated by a NUL byte.
It is possible to print in a custom format by using the --format option, which is able to interpolate different fields using a %(fieldname) notation. For example, if you only care about the "objectname" and "path" fields, you can execute with a specific "--format" like
git ls-files --format='%(objectname) %(path)'
The way each path is shown can be customized by using the --format=<format> option, where the %(fieldname) in the <format> string for various aspects of the index entry are interpolated. The following "fieldname" are understood:
git ls-files can use a list of "exclude patterns" when traversing the directory tree and finding files to show when the flags --others or --ignored are specified. the section called “gitignore(5)” specifies the format of exclude patterns.
These exclude patterns can be specified from the following places, in order:
A pattern specified on the command line with --exclude or read from the file specified with --exclude-from is relative to the top of the directory tree. A pattern read from a file specified by --exclude-per-directory is relative to the directory that the pattern file appears in.
Generally, you should be able to use --exclude-standard when you want the exclude rules applied the same way as what Porcelain commands do. To emulate what --exclude-standard specifies, you can give --exclude-per-directory=.gitignore, and then specify:
via the --exclude-from= option.
Part of the the section called “git(1)” suite
git ls-remote [--branches] [--tags] [--refs] [--upload-pack=<exec>]
[-q | --quiet] [--exit-code] [--get-url] [--sort=<key>]
[--symref] [<repository> [<patterns>…]]
Displays references available in a remote repository along with the associated commit IDs.
The output is in the format:
<oid> TAB <ref> LF
When showing an annotated tag, unless --refs is given, two such lines are shown: one with the refname for the tag itself as <ref>, and another with <ref> followed by ^{}. The <oid> on the latter line shows the name of the object the tag points at.
List all references (including symbolics and pseudorefs), peeling tags:
$ git ls-remote
27d43aaaf50ef0ae014b88bba294f93658016a2e HEAD
950264636c68591989456e3ba0a5442f93152c1a refs/heads/main
d9ab777d41f92a8c1684c91cfb02053d7dd1046b refs/heads/next
d4ca2e3147b409459955613c152220f4db848ee1 refs/tags/v2.40.0
73876f4861cd3d187a4682290ab75c9dccadbc56 refs/tags/v2.40.0^{}List all references matching given patterns:
$ git ls-remote http://www.kernel.org/pub/scm/git/git.git master seen rc 5fe978a5381f1fbad26a80e682ddd2a401966740 refs/heads/master c781a84b5204fb294c9ccc79f8b3baceeb32c061 refs/heads/seen
List only tags matching a given wildcard pattern:
$ git ls-remote --tags http://www.kernel.org/pub/scm/git/git.git v\*
485a869c64a68cc5795dd99689797c5900f4716d refs/tags/v2.39.2
cbf04937d5b9fcf0a76c28f69e6294e9e3ecd7e6 refs/tags/v2.39.2^{}
d4ca2e3147b409459955613c152220f4db848ee1 refs/tags/v2.40.0
73876f4861cd3d187a4682290ab75c9dccadbc56 refs/tags/v2.40.0^{}Part of the the section called “git(1)” suite
git ls-tree [-d] [-r] [-t] [-l] [-z]
[--name-only] [--name-status] [--object-only] [--full-name] [--full-tree] [--abbrev[=<n>]] [--format=<format>]
<tree-ish> [<path>…]
Lists the contents of a given tree object, like what "/bin/ls -a" does in the current working directory. Note that:
The output format of ls-tree is determined by either the --format option, or other format-altering options such as --name-only etc. (see --format above).
The use of certain --format directives is equivalent to using those options, but invoking the full formatting machinery can be slower than using an appropriate formatting option.
In cases where the --format would exactly map to an existing option ls-tree will use the appropriate faster path. Thus the default format is equivalent to:
%(objectmode) %(objecttype) %(objectname)%x09%(path)
This output format is compatible with what --index-info --stdin of git update-index expects.
When the -l option is used, format changes to
%(objectmode) %(objecttype) %(objectname) %(objectsize:padded)%x09%(path)
Object size identified by <objectname> is given in bytes, and right-justified with minimum width of 7 characters. Object size is given only for blobs (file) entries; for other entries - character is used in place of size.
Without the -z option, pathnames with "unusual" characters are quoted as explained for the configuration variable core.quotePath (see the section called “git-config(1)”). Using -z the filename is output verbatim and the line is terminated by a NUL byte.
Customized format:
It is possible to print in a custom format by using the --format option, which is able to interpolate different fields using a %(fieldname) notation. For example, if you only care about the "objectname" and "path" fields, you can execute with a specific "--format" like
git ls-tree --format='%(objectname) %(path)' <tree-ish>
Various values from structured fields can be used to interpolate into the resulting output. For each outputting line, the following names can be used:
Part of the the section called “git(1)” suite
git mailinfo [-k|-b] [-u | --encoding=<encoding> | -n]
[--[no-]scissors] [--quoted-cr=<action>]
<msg> <patch>
Reads a single e-mail message from the standard input, and writes the commit log message in <msg> file, and the patches in <patch> file. The author name, e-mail and e-mail subject are written out to the standard output to be used by git am to create a commit. It is usually not necessary to use this command directly. See the section called “git-am(1)” instead.
Usually the program removes email cruft from the Subject: header line to extract the title line for the commit log message. This option prevents this munging, and is most useful when used to read back git format-patch -k output.
Specifically, the following are removed until none of them remain:
Finally, runs of whitespace are normalized to a single ASCII space character.
The commit log message, author name and author email are taken from the e-mail, and after minimally decoding MIME transfer encoding, re-coded in the charset specified by i18n.commitEncoding (defaulting to UTF-8) by transliterating them. This used to be optional but now it is the default.
Note that the patch is always used as-is without charset conversion, even with this flag.
Remove everything in body before a scissors line (e.g. "-- >8 --"). The line represents scissors and perforation marks, and is used to request the reader to cut the message at that line. If that line appears in the body of the message before the patch, everything before it (including the scissors line itself) is ignored when this option is used.
This is useful if you want to begin your message in a discussion thread with comments and suggestions on the message you are responding to, and to conclude it with a patch submission, separating the discussion and the beginning of the proposed commit log message with a scissors line.
This can be enabled by default with the configuration option mailinfo.scissors.
Action when processes email messages sent with base64 or quoted-printable encoding, and the decoded lines end with a CRLF instead of a simple LF.
The valid actions are:
The default action could be set by configuration option mailinfo.quotedCR. If no such configuration option has been set, warn will be used.
Everything below this line in this section is selectively included from the the section called “git-config(1)” documentation. The content is the same as what's found there:
Part of the the section called “git(1)” suite
git mailsplit [-b] [-f<nn>] [-d<prec>] [--keep-cr] [--mboxrd]
-o<directory> [--] [(<mbox>|<Maildir>)…]
Splits a mbox file or a Maildir into a list of files: "0001" "0002" .. in the specified directory so you can process them further from there.
Maildir splitting relies upon filenames being sorted to output patches in the correct order.
Part of the the section called “git(1)” suite
git maintenance run [<options>]
git maintenance start [--scheduler=<scheduler>]
git maintenance (stop|register|unregister) [<options>]
Run tasks to optimize Git repository data, speeding up other Git commands and reducing storage requirements for the repository.
Git commands that add repository data, such as git add or git fetch, are optimized for a responsive user experience. These commands do not take time to optimize the Git data, since such optimizations scale with the full size of the repository while these user commands each perform a relatively small action.
The git maintenance command provides flexibility for how to optimize the Git repository.
Initialize Git config values so any scheduled maintenance will start running on this repository. This adds the repository to the maintenance.repo config variable in the current user's global config, or the config specified by --config-file option, and enables some recommended configuration values for maintenance.<task>.schedule. The tasks that are enabled are safe for running in the background without disrupting foreground processes.
The register subcommand will also set the maintenance.strategy config value to incremental, if this value is not previously set. The incremental strategy uses the following schedule for each maintenance task:
git maintenance register will also disable foreground maintenance by setting maintenance.auto = false in the current repository. This config setting will remain after a git maintenance unregister command.
Remove the current repository from background maintenance. This only removes the repository from the configured list. It does not stop the background maintenance processes from running.
The unregister subcommand will report an error if the current repository is not already registered. Use the --force option to return success even when the current repository is not registered.
The prefetch task updates the object directory with the latest objects from all registered remotes. For each remote, a git fetch command is run. The configured refspec is modified to place all requested refs within refs/prefetch/. Also, tags are not updated.
This is done to avoid disrupting the remote-tracking branches. The end users expect these refs to stay unmoved unless they initiate a fetch. However, with the prefetch task, the objects necessary to complete a later real fetch would already be obtained, making the real fetch faster. In the ideal case, it will just become an update to a bunch of remote-tracking branches without any object transfer.
The remote.<name>.skipFetchAll configuration can be used to exclude a particular remote from getting prefetched.
The loose-objects job cleans up loose objects and places them into pack-files. In order to prevent race conditions with concurrent Git commands, it follows a two-step process. First, it deletes any loose objects that already exist in a pack-file; concurrent Git processes will examine the pack-file for the object data instead of the loose object. Second, it creates a new pack-file (starting with "loose-") containing a batch of loose objects.
The batch size defaults to fifty thousand objects to prevent the job from taking too long on a repository with many loose objects. Use the maintenance.loose-objects.batchSize config option to adjust this size, including a value of 0 to remove the limit.
The gc task writes unreachable objects as loose objects to be cleaned up by a later step only if they are not re-added to a pack-file; for this reason it is not advisable to enable both the loose-objects and gc tasks at the same time.
The git maintenance command is designed to simplify the repository maintenance patterns while minimizing user wait time during Git commands. A variety of configuration options are available to allow customizing this process. The default maintenance options focus on operations that complete quickly, even on large repositories.
Users may find some cases where scheduled maintenance tasks do not run as frequently as intended. Each git maintenance run command takes a lock on the repository's object database, and this prevents other concurrent git maintenance run commands from running on the same repository. Without this safeguard, competing processes could leave the repository in an unpredictable state.
The background maintenance schedule runs git maintenance run processes on an hourly basis. Each run executes the "hourly" tasks. At midnight, that process also executes the "daily" tasks. At midnight on the first day of the week, that process also executes the "weekly" tasks. A single process iterates over each registered repository, performing the scheduled tasks for that frequency. The processes are scheduled to a random minute of the hour per client to spread out the load that multiple clients might generate (e.g. from prefetching). Depending on the number of registered repositories and their sizes, this process may take longer than an hour. In this case, multiple git maintenance run commands may run on the same repository at the same time, colliding on the object database lock. This results in one of the two tasks not running.
If you find that some maintenance windows are taking longer than one hour to complete, then consider reducing the complexity of your maintenance tasks. For example, the gc task is much slower than the incremental-repack task. However, this comes at a cost of a slightly larger object database. Consider moving more expensive tasks to be run less frequently.
Expert users may consider scheduling their own maintenance tasks using a different schedule than is available through git maintenance start and Git configuration options. These users should be aware of the object database lock and how concurrent git maintenance run commands behave. Further, the git gc command should not be combined with git maintenance run commands. git gc modifies the object database but does not take the lock in the same way as git maintenance run. If possible, use git maintenance run --task=gc instead of git gc.
The following sections describe the mechanisms put in place to run background maintenance by git maintenance start and how to customize them.
The standard mechanism for scheduling background tasks on POSIX systems is cron(8). This tool executes commands based on a given schedule. The current list of user-scheduled tasks can be found by running crontab -l. The schedule written by git maintenance start is similar to this:
# BEGIN GIT MAINTENANCE SCHEDULE # The following schedule was created by Git # Any edits made in this region might be # replaced in the future by a Git command. 0 1-23 * * * "/<path>/git" --exec-path="/<path>" for-each-repo --config=maintenance.repo maintenance run --schedule=hourly 0 0 * * 1-6 "/<path>/git" --exec-path="/<path>" for-each-repo --config=maintenance.repo maintenance run --schedule=daily 0 0 * * 0 "/<path>/git" --exec-path="/<path>" for-each-repo --config=maintenance.repo maintenance run --schedule=weekly # END GIT MAINTENANCE SCHEDULE
The comments are used as a region to mark the schedule as written by Git. Any modifications within this region will be completely deleted by git maintenance stop or overwritten by git maintenance start.
The crontab entry specifies the full path of the git executable to ensure that the executed git command is the same one with which git maintenance start was issued independent of PATH. If the same user runs git maintenance start with multiple Git executables, then only the latest executable is used.
These commands use git for-each-repo --config=maintenance.repo to run git maintenance run --schedule=<frequency> on each repository listed in the multi-valued maintenance.repo config option. These are typically loaded from the user-specific global config. The git maintenance process then determines which maintenance tasks are configured to run on each repository with each <frequency> using the maintenance.<task>.schedule config options. These values are loaded from the global or repository config values.
If the config values are insufficient to achieve your desired background maintenance schedule, then you can create your own schedule. If you run crontab -e, then an editor will load with your user-specific cron schedule. In that editor, you can add your own schedule lines. You could start by adapting the default schedule listed earlier, or you could read the crontab(5) documentation for advanced scheduling techniques. Please do use the full path and --exec-path techniques from the default schedule to ensure you are executing the correct binaries in your schedule.
While Linux supports cron, depending on the distribution, cron may be an optional package not necessarily installed. On modern Linux distributions, systemd timers are superseding it.
If user systemd timers are available, they will be used as a replacement of cron.
In this case, git maintenance start will create user systemd timer units and start the timers. The current list of user-scheduled tasks can be found by running systemctl --user list-timers. The timers written by git maintenance start are similar to this:
$ systemctl --user list-timers NEXT LEFT LAST PASSED UNIT ACTIVATES Thu 2021-04-29 19:00:00 CEST 42min left Thu 2021-04-29 18:00:11 CEST 17min ago git-maintenance@hourly.timer git-maintenance@hourly.service Fri 2021-04-30 00:00:00 CEST 5h 42min left Thu 2021-04-29 00:00:11 CEST 18h ago git-maintenance@daily.timer git-maintenance@daily.service Mon 2021-05-03 00:00:00 CEST 3 days left Mon 2021-04-26 00:00:11 CEST 3 days ago git-maintenance@weekly.timer git-maintenance@weekly.service
One timer is registered for each --schedule=<frequency> option.
The definition of the systemd units can be inspected in the following files:
~/.config/systemd/user/git-maintenance@.timer ~/.config/systemd/user/git-maintenance@.service ~/.config/systemd/user/timers.target.wants/git-maintenance@hourly.timer ~/.config/systemd/user/timers.target.wants/git-maintenance@daily.timer ~/.config/systemd/user/timers.target.wants/git-maintenance@weekly.timer
git maintenance start will overwrite these files and start the timer again with systemctl --user, so any customization should be done by creating a drop-in file, i.e. a .conf suffixed file in the ~/.config/systemd/user/git-maintenance@.service.d directory.
git maintenance stop will stop the user systemd timers and delete the above mentioned files.
For more details, see systemd.timer(5).
While macOS technically supports cron, using crontab -e requires elevated privileges and the executed process does not have a full user context. Without a full user context, Git and its credential helpers cannot access stored credentials, so some maintenance tasks are not functional.
Instead, git maintenance start interacts with the launchctl tool, which is the recommended way to schedule timed jobs in macOS. Scheduling maintenance through git maintenance (start|stop) requires some launchctl features available only in macOS 10.11 or later.
Your user-specific scheduled tasks are stored as XML-formatted .plist files in ~/Library/LaunchAgents/. You can see the currently-registered tasks using the following command:
$ ls ~/Library/LaunchAgents/org.git-scm.git* org.git-scm.git.daily.plist org.git-scm.git.hourly.plist org.git-scm.git.weekly.plist
One task is registered for each --schedule=<frequency> option. To inspect how the XML format describes each schedule, open one of these .plist files in an editor and inspect the <array> element following the <key>StartCalendarInterval</key> element.
git maintenance start will overwrite these files and register the tasks again with launchctl, so any customizations should be done by creating your own .plist files with distinct names. Similarly, the git maintenance stop command will unregister the tasks with launchctl and delete the .plist files.
To create more advanced customizations to your background tasks, see launchctl.plist(5) for more information.
Windows does not support cron and instead has its own system for scheduling background tasks. The git maintenance start command uses the schtasks command to submit tasks to this system. You can inspect all background tasks using the Task Scheduler application. The tasks added by Git have names of the form Git Maintenance (<frequency>). The Task Scheduler GUI has ways to inspect these tasks, but you can also export the tasks to XML files and view the details there.
Note that since Git is a console application, these background tasks create a console window visible to the current user. This can be changed manually by selecting the "Run whether user is logged in or not" option in Task Scheduler. This change requires a password input, which is why git maintenance start does not select it by default.
If you want to customize the background tasks, please rename the tasks so future calls to git maintenance (start|stop) do not overwrite your custom tasks.
Everything below this line in this section is selectively included from the the section called “git-config(1)” documentation. The content is the same as what's found there:
Many Git commands trigger automatic maintenance after they have written data into the repository. This boolean config option controls whether this automatic maintenance shall happen in the foreground or whether the maintenance process shall detach and continue to run in the background.
If unset, the value of gc.autoDetach is used as a fallback. Defaults to true if both are unset, meaning that the maintenance process will detach.
This string config option provides a way to specify one of a few recommended schedules for background maintenance. This only affects which tasks are run during git maintenance run --schedule=X commands, provided no --task=<task> arguments are provided. Further, if a maintenance.<task>.schedule config value is set, then that value is used instead of the one provided by maintenance.strategy. The possible strategy strings are:
Part of the the section called “git(1)” suite
git merge-base [-a | --all] <commit> <commit>…
git merge-base [-a | --all] --octopus <commit>…
git merge-base --is-ancestor <commit> <commit>
git merge-base --independent <commit>…
git merge-base --fork-point <ref> [<commit>]
git merge-base finds the best common ancestor(s) between two commits to use in a three-way merge. One common ancestor is better than another common ancestor if the latter is an ancestor of the former. A common ancestor that does not have any better common ancestor is a best common ancestor, i.e. a merge base. Note that there can be more than one merge base for a pair of commits.
In the most common special case, specifying only two commits on the command line means computing the merge base between the given two commits.
More generally, among the two commits to compute the merge base from, one is specified by the first commit argument on the command line; the other commit is a (possibly hypothetical) commit that is a merge across all the remaining commits on the command line.
As a consequence, the merge base is not necessarily contained in each of the commit arguments if more than two commits are specified. This is different from the section called “git-show-branch(1)” when used with the --merge-base option.
Given two commits A and B, git merge-base A B will output a commit which is reachable from both A and B through the parent relationship.
For example, with this topology:
o---o---o---B
/
---o---1---o---o---o---Athe merge base between A and B is 1.
Given three commits A, B, and C, git merge-base A B C will compute the merge base between A and a hypothetical commit M, which is a merge between B and C. For example, with this topology:
o---o---o---o---C
/
/ o---o---o---B
/ /
---2---1---o---o---o---Athe result of git merge-base A B C is 1. This is because the equivalent topology with a merge commit M between B and C is:
o---o---o---o---o
/ \
/ o---o---o---o---M
/ /
---2---1---o---o---o---Aand the result of git merge-base A M is 1. Commit 2 is also a common ancestor between A and M, but 1 is a better common ancestor, because 2 is an ancestor of 1. Hence, 2 is not a merge base.
The result of git merge-base --octopus A B C is 2, because 2 is the best common ancestor of all commits.
When the history involves criss-cross merges, there can be more than one best common ancestor for two commits. For example, with this topology:
---1---o---A
\ /
X
/ \
---2---o---o---Bboth 1 and 2 are merge bases of A and B. Neither one is better than the other (both are best merge bases). When the --all option is not given, it is unspecified which best one is output.
A common idiom to check "fast-forward-ness" between two commits A and B is (or at least used to be) to compute the merge base between A and B, and check if it is the same as A, in which case, A is an ancestor of B. You will see this idiom used often in older scripts.
A=$(git rev-parse --verify A)
if test "$A" = "$(git merge-base A B)"
then
... A is an ancestor of B ...
fiIn modern git, you can say this in a more direct way:
if git merge-base --is-ancestor A B
then
... A is an ancestor of B ...
fiinstead.
After working on the topic branch created with git switch -c topic origin/master, the history of remote-tracking branch origin/master may have been rewound and rebuilt, leading to a history of this shape:
o---B2
/
---o---o---B1--o---o---o---B (origin/master)
\
B0
\
D0---D1---D (topic)where origin/master used to point at commits B0, B1, B2 and now it points at B, and your topic branch was started on top of it back when origin/master was at B0, and you built three commits, D0, D1, and D, on top of it. Imagine that you now want to rebase the work you did on the topic on top of the updated origin/master.
In such a case, git merge-base origin/master topic would return the parent of B0 in the above picture, but B0^..D is not the range of commits you would want to replay on top of B (it includes B0, which is not what you wrote; it is a commit the other side discarded when it moved its tip from B0 to B1).
git merge-base --fork-point origin/master topic is designed to help in such a case. It takes not only B but also B0, B1, and B2 (i.e. old tips of the remote-tracking branches your repository's reflog knows about) into account to see on which commit your topic branch was built and finds B0, allowing you to replay only the commits on your topic, excluding the commits the other side later discarded.
Hence
$ fork_point=$(git merge-base --fork-point origin/master topic)
will find B0, and
$ git rebase --onto origin/master $fork_point topic
will replay D0, D1, and D on top of B to create a new history of this shape:
o---B2
/
---o---o---B1--o---o---o---B (origin/master)
\ \
B0 D0'--D1'--D' (topic - updated)
\
D0---D1---D (topic - old)A caveat is that older reflog entries in your repository may be expired by git gc. If B0 no longer appears in the reflog of the remote-tracking branch origin/master, the --fork-point mode obviously cannot find it and fails, avoiding to give a random and useless result (such as the parent of B0, like the same command without the --fork-point option gives).
Also, the remote-tracking branch you use the --fork-point mode with must be the one your topic forked from its tip. If you forked from an older commit than the tip, this mode would not find the fork point (imagine in the above sample history B0 did not exist, origin/master started at B1, moved to B2 and then B, and you forked your topic at origin/master^ when origin/master was B1; the shape of the history would be the same as above, without B0, and the parent of B1 is what git merge-base origin/master topic correctly finds, but the --fork-point mode will not, because it is not one of the commits that used to be at the tip of origin/master).
the section called “git-rev-list(1)”, the section called “git-show-branch(1)”, the section called “git-merge(1)”
Part of the the section called “git(1)” suite
git merge-file [-L <current-name> [-L <base-name> [-L <other-name>]]]
[--ours|--theirs|--union] [-p|--stdout] [-q|--quiet] [--marker-size=<n>]
[--[no-]diff3] [--object-id] <current> <base> <other>
Given three files <current>, <base> and <other>, git merge-file incorporates all changes that lead from <base> to <other> into <current>. The result ordinarily goes into <current>. git merge-file is useful for combining separate changes to an original. Suppose <base> is the original, and both <current> and <other> are modifications of <base>, then git merge-file combines both changes.
A conflict occurs if both <current> and <other> have changes in a common segment of lines. If a conflict is found, git merge-file normally outputs a warning and brackets the conflict with lines containing <<<<<<< and >>>>>>> markers. A typical conflict will look like this:
<<<<<<< A lines in file A ======= lines in file B >>>>>>> B
If there are conflicts, the user should edit the result and delete one of the alternatives. When --ours, --theirs, or --union option is in effect, however, these conflicts are resolved favouring lines from <current>, lines from <other>, or lines from both respectively. The length of the conflict markers can be given with the --marker-size option.
If --object-id is specified, exactly the same behavior occurs, except that instead of specifying what to merge as files, it is specified as a list of object IDs referring to blobs.
The exit value of this program is negative on error, and the number of conflicts otherwise (truncated to 127 if there are more than that many conflicts). If the merge was clean, the exit value is 0.
git merge-file is designed to be a minimal clone of RCS merge; that is, it implements all of RCS merge's functionality which is needed by the section called “git(1)”.
Specify the contents to merge as blobs in the current repository instead of files. In this case, the operation must take place within a valid repository.
If the -p option is specified, the merged file (including conflicts, if any) goes to standard output as normal; otherwise, the merged file is written to the object store and the object ID of its blob is written to standard output.
Part of the the section called “git(1)” suite
This looks up the <file>(s) in the index and, if there are any merge entries, passes the SHA-1 hash for those files as arguments 1, 2, 3 (empty argument if no file), and <file> as argument 4. File modes for the three files are passed as arguments 5, 6 and 7.
If git merge-index is called with multiple <file>s (or -a) then it processes them in turn only stopping if merge returns a non-zero exit code.
Typically this is run with a script calling Git's imitation of the merge command from the RCS package.
A sample script called git merge-one-file is included in the distribution.
ALERT ALERT ALERT! The Git "merge object order" is different from the RCS merge program merge object order. In the above ordering, the original is first. But the argument order to the 3-way merge program merge is to have the original in the middle. Don't ask me why.
Examples:
torvalds@ppc970:~/merge-test> git merge-index cat MM This is MM from the original tree. # original This is modified MM in the branch A. # merge1 This is modified MM in the branch B. # merge2 This is modified MM in the branch B. # current contents
or
torvalds@ppc970:~/merge-test> git merge-index cat AA MM cat: : No such file or directory This is added AA in the branch A. This is added AA in the branch B. This is added AA in the branch B. fatal: merge program failed
where the latter example shows how git merge-index will stop trying to merge once anything has returned an error (i.e., cat returned an error for the AA file, because it didn't exist in the original, and thus git merge-index didn't even try to merge the MM thing).
Part of the the section called “git(1)” suite
This is the standard helper program to use with git merge-index to resolve a merge after the trivial merge done with git read-tree -m.
Part of the the section called “git(1)” suite
git merge-tree [--write-tree] [<options>] <branch1> <branch2>
git merge-tree [--trivial-merge] <base-tree> <branch1> <branch2> (deprecated)
This command has a modern --write-tree mode and a deprecated --trivial-merge mode. With the exception of the DEPRECATED DESCRIPTION section at the end, the rest of this documentation describes the modern --write-tree mode.
Performs a merge, but does not make any new commits and does not read from or write to either the working tree or index.
The performed merge will use the same features as the "real" the section called “git-merge(1)”, including:
After the merge completes, a new toplevel tree object is created. See OUTPUT below for details.
Instead of finding the merge-bases for <branch1> and <branch2>, specify a merge-base for the merge, and specifying multiple bases is currently not supported. This option is incompatible with --stdin.
As the merge-base is provided directly, <branch1> and <branch2> do not need to specify commits; trees are enough.
For a successful merge, the output from git-merge-tree is simply one line:
<OID of toplevel tree>
Whereas for a conflicted merge, the output is by default of the form:
<OID of toplevel tree> <Conflicted file info> <Informational messages>
These are discussed individually below.
However, there is an exception. If --stdin is passed, then there is an extra section at the beginning, a NUL character at the end, and then all the sections repeat for each line of input. Thus, if the first merge is conflicted and the second is clean, the output would be of the form:
<Merge status> <OID of toplevel tree> <Conflicted file info> <Informational messages> NUL <Merge status> <OID of toplevel tree> NUL
This is an integer status followed by a NUL character. The integer status is:
0: merge had conflicts 1: merge was clean
This is a tree object that represents what would be checked out in the working tree at the end of git merge. If there were conflicts, then files within this tree may have embedded conflict markers. This section is always followed by a newline (or NUL if -z is passed).
This is a sequence of lines with the format
<mode> <object> <stage> <filename>
The filename will be quoted as explained for the configuration variable core.quotePath (see the section called “git-config(1)”). However, if the --name-only option is passed, the mode, object, and stage will be omitted. If -z is passed, the "lines" are terminated by a NUL character instead of a newline character.
This section provides informational messages, typically about conflicts. The format of the section varies significantly depending on whether -z is passed.
If -z is passed:
The output format is zero or more conflict informational records, each of the form:
<list-of-paths><conflict-type>NUL<conflict-message>NUL
where <list-of-paths> is of the form
<number-of-paths>NUL<path1>NUL<path2>NUL...<pathN>NUL
and includes paths (or branch names) affected by the conflict or informational message in <conflict-message>. Also, <conflict-type> is a stable string explaining the type of conflict, such as
and <conflict-message> is a more detailed message about the conflict which often (but not always) embeds the <stable-short-type-description> within it. These strings may change in future Git versions. Some examples:
If -z is NOT passed:
This section starts with a blank line to separate it from the previous sections, and then only contains the <conflict-message> information from the previous section (separated by newlines). These are non-stable strings that should not be parsed by scripts, and are just meant for human consumption. Also, note that while <conflict-message> strings usually do not contain embedded newlines, they sometimes do. (However, the free-form messages will never have an embedded NUL character). So, the entire block of information is meant for human readers as an agglomeration of all conflict messages.
For a successful, non-conflicted merge, the exit status is 0. When the merge has conflicts, the exit status is 1. If the merge is not able to complete (or start) due to some kind of error, the exit status is something other than 0 or 1 (and the output is unspecified). When --stdin is passed, the return status is 0 for both successful and conflicted merges, and something other than 0 or 1 if it cannot complete all the requested merges.
This command is intended as low-level plumbing, similar to the section called “git-hash-object(1)”, the section called “git-mktree(1)”, the section called “git-commit-tree(1)”, the section called “git-write-tree(1)”, the section called “git-update-ref(1)”, and the section called “git-mktag(1)”. Thus, it can be used as a part of a series of steps such as:
vi message.txt
BRANCH1=refs/heads/test
BRANCH2=main
NEWTREE=$(git merge-tree --write-tree $BRANCH1 $BRANCH2) || {
echo "There were conflicts..." 1>&2
exit 1
}
NEWCOMMIT=$(git commit-tree $NEWTREE -F message.txt \
-p $BRANCH1 -p $BRANCH2)
git update-ref $BRANCH1 $NEWCOMMITNote that when the exit status is non-zero, NEWTREE in this sequence will contain a lot more output than just a tree.
For conflicts, the output includes the same information that you'd get with the section called “git-merge(1)”:
git merge-tree --stdin input format is fully text based. Each line has this format:
[<base-commit> -- ]<branch1> <branch2>
If one line is separated by --, the string before the separator is used for specifying a merge-base for the merge and the string after the separator describes the branches to be merged.
Do NOT look through the resulting toplevel tree to try to find which files conflict; parse the Conflicted file info section instead. Not only would parsing an entire tree be horrendously slow in large repositories, there are numerous types of conflicts not representable by conflict markers (modify/delete, mode conflict, binary file changed on both sides, file/directory conflicts, various rename conflict permutations, etc.)
Do NOT interpret an empty Conflicted file info list as a clean merge; check the exit status. A merge can have conflicts without having individual files conflict (there are a few types of directory rename conflicts that fall into this category, and others might also be added in the future).
Do NOT attempt to guess or make the user guess the conflict types from the Conflicted file info list. The information there is insufficient to do so. For example: Rename/rename(1to2) conflicts (both sides renamed the same file differently) will result in three different files having higher order stages (but each only has one higher order stage), with no way (short of the Informational messages section) to determine which three files are related. File/directory conflicts also result in a file with exactly one higher order stage. Possibly-involved-in-directory-rename conflicts (when "merge.directoryRenames" is unset or set to "conflicts") also result in a file with exactly one higher order stage. In all cases, the Informational messages section has the necessary info, though it is not designed to be machine parseable.
Do NOT assume that each path from Conflicted file info, and the logical conflicts in the Informational messages have a one-to-one mapping, nor that there is a one-to-many mapping, nor a many-to-one mapping. Many-to-many mappings exist, meaning that each path can have many logical conflict types in a single merge, and each logical conflict type can affect many paths.
Do NOT assume all filenames listed in the Informational messages section had conflicts. Messages can be included for files that have no conflicts, such as "Auto-merging <file>".
AVOID taking the OIDS from the Conflicted file info and re-merging them to present the conflicts to the user. This will lose information. Instead, look up the version of the file found within the OID of toplevel tree and show that instead. In particular, the latter will have conflict markers annotated with the original branch/commit being merged and, if renames were involved, the original filename. While you could include the original branch/commit in the conflict marker annotations when re-merging, the original filename is not available from the Conflicted file info and thus you would be losing information that might help the user resolve the conflict.
Per the DESCRIPTION and unlike the rest of this documentation, this section describes the deprecated --trivial-merge mode.
Other than the optional --trivial-merge, this mode accepts no options.
This mode reads three tree-ish, and outputs trivial merge results and conflicting stages to the standard output in a semi-diff format. Since this was designed for higher level scripts to consume and merge the results back into the index, it omits entries that match <branch1>. The result of this second form is similar to what three-way git read-tree -m does, but instead of storing the results in the index, the command outputs the entries to the standard output.
This form not only has limited applicability (a trivial merge cannot handle content merges of individual files, rename detection, proper directory/file conflict handling, etc.), the output format is also difficult to work with, and it will generally be less performant than the first form even on successful merges (especially if working in large repositories).
Part of the the section called “git(1)” suite
gitmerge[-n] [--stat] [--no-commit] [--squash] [--[no-]edit]
[--no-verify] [-s<strategy>] [-X<strategy-option>] [-S[<keyid>]]
[--[no-]allow-unrelated-histories]
[--[no-]rerere-autoupdate] [-m<msg>] [-F<file>]
[--into-name<branch>] [<commit>…]
gitmerge(--continue|--abort|--quit)
Incorporates changes from the named commits (since the time their histories diverged from the current branch) into the current branch. This command is used by git pull to incorporate changes from another repository and can be used by hand to merge changes from one branch into another.
Assume the following history exists and the current branch is master:
A---B---C topic
/
D---E---F---G masterThen git merge topic will replay the changes made on the topic branch since it diverged from master (i.e., E) until its current commit (C) on top of master, and record the result in a new commit along with the names of the two parent commits and a log message from the user describing the changes. Before the operation, ORIG_HEAD is set to the tip of the current branch (C).
A---B---C topic
/ \
D---E---F---G---H masterA merge stops if there's a conflict that cannot be resolved automatically or if --no-commit was provided when initiating the merge. At that point you can run git merge --abort or git merge --continue.
git merge --abort will abort the merge process and try to reconstruct the pre-merge state. However, if there were uncommitted changes when the merge started (and especially if those changes were further modified after the merge was started), git merge --abort will in some cases be unable to reconstruct the original (pre-merge) changes. Therefore:
Running git merge with non-trivial uncommitted changes is discouraged: while possible, it may leave you in a state that is hard to back out of in the case of a conflict.
Perform the merge and commit the result. This option can be used to override --no-commit.
With --no-commit perform the merge and stop just before creating a merge commit, to give the user a chance to inspect and further tweak the merge result before committing.
Note that fast-forward updates do not create a merge commit and therefore there is no way to stop those merges with --no-commit. Thus, if you want to ensure your branch is not changed or updated by the merge command, use --no-ff with --no-commit.
Invoke an editor before committing successful mechanical merge to further edit the auto-generated merge message, so that the user can explain and justify the merge. The --no-edit option can be used to accept the auto-generated message (this is generally discouraged). The --edit (or -e) option is still useful if you are giving a draft message with the -m option from the command line and want to edit it in the editor.
Older scripts may depend on the historical behaviour of not allowing the user to edit the merge log message. They will see an editor opened when they run git merge. To make it easier to adjust such scripts to the updated behaviour, the environment variable GIT_MERGE_AUTOEDIT can be set to no at the beginning of them.
Specifies how a merge is handled when the merged-in history is already a descendant of the current history. --ff is the default unless merging an annotated (and possibly signed) tag that is not stored in its natural place in the refs/tags/ hierarchy, in which case --no-ff is assumed.
With --ff, when possible resolve the merge as a fast-forward (only update the branch pointer to match the merged branch; do not create a merge commit). When not possible (when the merged-in history is not a descendant of the current history), create a merge commit.
With --no-ff, create a merge commit in all cases, even when the merge could instead be resolved as a fast-forward.
With --ff-only, resolve the merge as a fast-forward when possible. When not possible, refuse to merge and exit with a non-zero status.
In addition to branch names, populate the log message with one-line descriptions from at most <n> actual commits that are being merged. See also the section called “git-fmt-merge-msg(1)”.
With --no-log do not list one-line descriptions from the actual commits being merged.
Add a Signed-off-by trailer by the committer at the end of the commit log message. The meaning of a signoff depends on the project to which you're committing. For example, it may certify that the committer has the rights to submit the work under the project's license or agrees to some contributor representation, such as a Developer Certificate of Origin. (See https://developercertificate.org for the one used by the Linux kernel and Git projects.) Consult the documentation or leadership of the project to which you're contributing to understand how the signoffs are used in that project.
The --no-signoff option can be used to countermand an earlier --signoff option on the command line.
Show a diffstat at the end of the merge. The diffstat is also controlled by the configuration option merge.stat.
With -n or --no-stat do not show a diffstat at the end of the merge.
Produce the working tree and index state as if a real merge happened (except for the merge information), but do not actually make a commit, move the HEAD, or record $GIT_DIR/MERGE_HEAD (to cause the next git commit command to create a merge commit). This allows you to create a single commit on top of the current branch whose effect is the same as merging another branch (or more in case of an octopus).
With --no-squash perform the merge and commit the result. This option can be used to override --squash.
With --squash, --commit is not allowed, and will fail.
Set the commit message to be used for the merge commit (in case one is created).
If --log is specified, a shortlog of the commits being merged will be appended to the specified message.
The git fmt-merge-msg command can be used to give a good default for automated git merge invocations. The automated message can include the branch description.
Read the commit message to be used for the merge commit (in case one is created).
If --log is specified, a shortlog of the commits being merged will be appended to the specified message.
Abort the current conflict resolution process, and try to reconstruct the pre-merge state. If an autostash entry is present, apply it to the worktree.
If there were uncommitted worktree changes present when the merge started, git merge --abort will in some cases be unable to reconstruct these changes. It is therefore recommended to always commit or stash your changes before running git merge.
git merge --abort is equivalent to git reset --merge when MERGE_HEAD is present unless MERGE_AUTOSTASH is also present in which case git merge --abort applies the stash entry to the worktree whereas git reset --merge will save the stashed changes in the stash list.
Commits, usually other branch heads, to merge into our branch. Specifying more than one commit will create a merge with more than two parents (affectionately called an Octopus merge).
If no commit is given from the command line, merge the remote-tracking branches that the current branch is configured to use as its upstream. See also the configuration section of this manual page.
When FETCH_HEAD (and no other commit) is specified, the branches recorded in the .git/FETCH_HEAD file by the previous invocation of git fetch for merging are merged to the current branch.
Before applying outside changes, you should get your own work in good shape and committed locally, so it will not be clobbered if there are conflicts. See also the section called “git-stash(1)”. git pull and git merge will stop without doing anything when local uncommitted changes overlap with files that git pull/git merge may need to update.
To avoid recording unrelated changes in the merge commit, git pull and git merge will also abort if there are any changes registered in the index relative to the HEAD commit. (Special narrow exceptions to this rule may exist depending on which merge strategy is in use, but generally, the index must match HEAD.)
If all named commits are already ancestors of HEAD, git merge will exit early with the message "Already up to date."
Often the current branch head is an ancestor of the named commit. This is the most common case especially when invoked from git pull: you are tracking an upstream repository, you have committed no local changes, and now you want to update to a newer upstream revision. In this case, a new commit is not needed to store the combined history; instead, the HEAD (along with the index) is updated to point at the named commit, without creating an extra merge commit.
This behavior can be suppressed with the --no-ff option.
Except in a fast-forward merge (see above), the branches to be merged must be tied together by a merge commit that has both of them as its parents.
A merged version reconciling the changes from all branches to be merged is committed, and your HEAD, index, and working tree are updated to it. It is possible to have modifications in the working tree as long as they do not overlap; the update will preserve them.
When it is not obvious how to reconcile the changes, the following happens:
<<< === >>>.
If you tried a merge which resulted in complex conflicts and want to start over, you can recover with git merge --abort.
When merging an annotated (and possibly signed) tag, Git always creates a merge commit even if a fast-forward merge is possible, and the commit message template is prepared with the tag message. Additionally, if the tag is signed, the signature check is reported as a comment in the message template. See also the section called “git-tag(1)”.
When you want to just integrate with the work leading to the commit that happens to be tagged, e.g. synchronizing with an upstream release point, you may not want to make an unnecessary merge commit.
In such a case, you can "unwrap" the tag yourself before feeding it to git merge, or pass --ff-only when you do not have any work on your own. e.g.
git fetch origin git merge v1.2.3^0 git merge --ff-only v1.2.3
During a merge, the working tree files are updated to reflect the result of the merge. Among the changes made to the common ancestor's version, non-overlapping ones (that is, you changed an area of the file while the other side left that area intact, or vice versa) are incorporated in the final result verbatim. When both sides made changes to the same area, however, Git cannot randomly pick one side over the other, and asks you to resolve it by leaving what both sides did to that area.
By default, Git uses the same style as the one used by the "merge" program from the RCS suite to present such a conflicted hunk, like this:
Here are lines that are either unchanged from the common ancestor, or cleanly resolved because only one side changed, or cleanly resolved because both sides changed the same way. <<<<<<< yours:sample.txt Conflict resolution is hard; let's go shopping. ======= Git makes conflict resolution easy. >>>>>>> theirs:sample.txt And here is another line that is cleanly resolved or unmodified.
The area where a pair of conflicting changes happened is marked with markers
<<<<<<<, =======, and >>>>>>>. The part before the =======
is typically your side, and the part afterwards is typically their side.
The default format does not show what the original said in the conflicting area. You cannot tell how many lines are deleted and replaced with Barbie's remark on your side. The only thing you can tell is that your side wants to say it is hard and you'd prefer to go shopping, while the other side wants to claim it is easy.
An alternative style can be used by setting the merge.conflictStyle configuration variable to either diff3 or zdiff3. In diff3 style, the above conflict may look like this:
Here are lines that are either unchanged from the common ancestor, or cleanly resolved because only one side changed, <<<<<<< yours:sample.txt or cleanly resolved because both sides changed the same way. Conflict resolution is hard; let's go shopping. ||||||| base:sample.txt or cleanly resolved because both sides changed identically. Conflict resolution is hard. ======= or cleanly resolved because both sides changed the same way. Git makes conflict resolution easy. >>>>>>> theirs:sample.txt And here is another line that is cleanly resolved or unmodified.
while in zdiff3 style, it may look like this:
Here are lines that are either unchanged from the common ancestor, or cleanly resolved because only one side changed, or cleanly resolved because both sides changed the same way. <<<<<<< yours:sample.txt Conflict resolution is hard; let's go shopping. ||||||| base:sample.txt or cleanly resolved because both sides changed identically. Conflict resolution is hard. ======= Git makes conflict resolution easy. >>>>>>> theirs:sample.txt And here is another line that is cleanly resolved or unmodified.
In addition to the <<<<<<<, =======, and >>>>>>> markers, it uses
another ||||||| marker that is followed by the original text. You can
tell that the original just stated a fact, and your side simply gave in to
that statement and gave up, while the other side tried to have a more
positive attitude. You can sometimes come up with a better resolution by
viewing the original.
After seeing a conflict, you can do two things:
You can work through the conflict with a number of tools:
Merge branches fixes and enhancements on top of the current branch, making an octopus merge:
$ git merge fixes enhancements
Merge branch obsolete into the current branch, using ours merge strategy:
$ git merge -s ours obsolete
Merge branch maint into the current branch, but do not make a new commit automatically:
$ git merge --no-commit maint
This can be used when you want to include further changes to the merge, or want to write your own merge commit message.
You should refrain from abusing this option to sneak substantial changes into a merge commit. Small fixups like bumping release/version name would be acceptable.
The merge mechanism (git merge and git pull commands) allows the backend merge strategies to be chosen with -s option. Some strategies can also take their own options, which can be passed by giving -X<option> arguments to git merge and/or git pull.
This is the default merge strategy when pulling or merging one branch. This strategy can only resolve two heads using a 3-way merge algorithm. When there is more than one common ancestor that can be used for 3-way merge, it creates a merged tree of the common ancestors and uses that as the reference tree for the 3-way merge. This has been reported to result in fewer merge conflicts without causing mismerges by tests done on actual merge commits taken from Linux 2.6 kernel development history. Additionally this strategy can detect and handle merges involving renames. It does not make use of detected copies. The name for this algorithm is an acronym ("Ostensibly Recursive's Twin") and came from the fact that it was written as a replacement for the previous default algorithm, recursive.
In the case where the path is a submodule, if the submodule commit used on one side of the merge is a descendant of the submodule commit used on the other side of the merge, Git attempts to fast-forward to the descendant. Otherwise, Git will treat this case as a conflict, suggesting as a resolution a submodule commit that is descendant of the conflicting ones, if one exists.
The ort strategy can take the following options:
This option forces conflicting hunks to be auto-resolved cleanly by favoring our version. Changes from the other tree that do not conflict with our side are reflected in the merge result. For a binary file, the entire contents are taken from our side.
This should not be confused with the ours merge strategy, which does not even look at what the other tree contains at all. It discards everything the other tree did, declaring our history contains all that happened in it.
Treats lines with the indicated type of whitespace change as unchanged for the sake of a three-way merge. Whitespace changes mixed with other changes to a line are not ignored. See also the section called “git-diff(1)” -b, -w, --ignore-space-at-eol, and --ignore-cr-at-eol.
With the strategies that use 3-way merge (including the default, ort), if a change is made on both branches, but later reverted on one of the branches, that change will be present in the merged result; some people find this behavior confusing. It occurs because only the heads and the merge base are considered when performing a merge, not the individual commits. The merge algorithm therefore considers the reverted change as no change at all, and substitutes the changed version instead.
Everything above this line in this section isn't included from the the section called “git-config(1)” documentation. The content that follows is the same as what's found there:
<<<<<<< conflict marker, changes made by one side,
a ======= marker, changes made by the other side, and then
a >>>>>>> marker. An alternate style, "diff3", adds a |||||||
marker and the original text before the ======= marker. The
"merge" style tends to produce smaller conflict regions than diff3,
both because of the exclusion of the original text, and because
when a subset of lines match on the two sides, they are just pulled
out of the conflict region. Another alternate style, "zdiff3", is
similar to diff3 but removes matching lines on the two sides from
the conflict region when those matching lines appear near either
the beginning or end of a conflict region.
By adding a glob that matches the names of integration branches to this multi-valued configuration variable, the default merge message computed for merges into these integration branches will omit "into <branch-name>" from its title.
An element with an empty value can be used to clear the list of globs accumulated from previous configuration entries. When there is no merge.suppressDest variable defined, the default value of master is used for backward compatibility.
Whether Git detects directory renames, affecting what happens at merge time to new files added to a directory on one side of history when that directory was renamed on the other side of history. Possible values are:
If merge.renames is false, merge.directoryRenames is ignored and treated as false. Defaults to conflict.
Controls which merge tool is used by the section called “git-mergetool(1)” when the -g/--gui flag is specified. The list below shows the valid built-in values. Any other value is treated as a custom merge tool and requires that a corresponding mergetool.<guitool>.cmd variable is defined.
the section called “git-fmt-merge-msg(1)”, the section called “git-pull(1)”, the section called “gitattributes(5)”, the section called “git-reset(1)”, the section called “git-diff(1)”, the section called “git-ls-files(1)”, the section called “git-add(1)”, the section called “git-rm(1)”, the section called “git-mergetool(1)”
Part of the the section called “git(1)” suite
This is not a command the end user would want to run. Ever. This documentation is meant for people who are studying the Porcelain-ish scripts and/or are writing new ones.
The git-mergetool--lib scriptlet is designed to be sourced (using .) by other shell scripts to set up functions for working with Git merge tools.
Before sourcing git-mergetool--lib, your script must set TOOL_MODE to define the operation mode for the functions listed below. diff and merge are valid values.
Part of the the section called “git(1)” suite
Use git mergetool to run one of several merge utilities to resolve merge conflicts. It is typically run after git merge.
If one or more <file> parameters are given, the merge tool program will be run to resolve differences in each file (skipping those without conflicts). Specifying a directory will include all unresolved files in that path. If no <file> names are specified, git mergetool will run the merge tool program on every file with merge conflicts.
Use the merge resolution program specified by <tool>. Valid values include emerge, gvimdiff, kdiff3, meld, vimdiff, and tortoisemerge. Run git mergetool --tool-help for the list of valid <tool> settings.
If a merge resolution program is not specified, git mergetool will use the configuration variable merge.tool. If the configuration variable merge.tool is not set, git mergetool will pick a suitable default.
You can explicitly provide a full path to the tool by setting the configuration variable mergetool.<tool>.path. For example, you can configure the absolute path to kdiff3 by setting mergetool.kdiff3.path. Otherwise, git mergetool assumes the tool is available in $PATH.
Instead of running one of the known merge tool programs, git mergetool can be customized to run an alternative program by specifying the command line to invoke in a configuration variable mergetool.<tool>.cmd.
When git mergetool is invoked with this tool (either through the -t or --tool option or the merge.tool configuration variable), the configured command line will be invoked with BASE set to the name of a temporary file containing the common base for the merge, if available; LOCAL set to the name of a temporary file containing the contents of the file on the current branch; REMOTE set to the name of a temporary file containing the contents of the file to be merged, and MERGED set to the name of the file to which the merge tool should write the result of the merge resolution.
If the custom merge tool correctly indicates the success of a merge resolution with its exit code, then the configuration variable mergetool.<tool>.trustExitCode can be set to true. Otherwise, git mergetool will prompt the user to indicate the success of the resolution after the custom tool has exited.
Everything below this line in this section is selectively included from the the section called “git-config(1)” documentation. The content is the same as what's found there:
git mergetool creates *.orig backup files while resolving merges. These are safe to remove once a file has been merged and its git mergetool session has completed.
Setting the mergetool.keepBackup configuration variable to false causes git mergetool to automatically remove the backup files as files are successfully merged.
When specifying --tool=vimdiff in git mergetool Git will open Vim with a 4 windows layout distributed in the following way:
------------------------------------------ | | | | | LOCAL | BASE | REMOTE | | | | | ------------------------------------------ | | | MERGED | | | ------------------------------------------
LOCAL, BASE and REMOTE are read-only buffers showing the contents of the conflicting file in specific commits ("commit you are merging into", "common ancestor commit" and "commit you are merging from" respectively)
MERGED is a writable buffer where you have to resolve the conflicts (using the other read-only buffers as a reference). Once you are done, save and exit Vim as usual (:wq) or, if you want to abort, exit using :cq.
You can change the windows layout used by Vim by setting configuration variable mergetool.vimdiff.layout which accepts a string where the following separators have special meaning:
The precedence of the operators is as follows (you can use parentheses to change it):
`@` > `+` > `/` > `,`
Let's see some examples to understand how it works:
layout = "(LOCAL,BASE,REMOTE)/MERGED"
This is exactly the same as the default layout we have already seen.
Note that / has precedence over , and thus the parenthesis are not needed in this case. The next layout definition is equivalent:
layout = "LOCAL,BASE,REMOTE / MERGED"
layout = "LOCAL,MERGED,REMOTE"
If, for some reason, we are not interested in the BASE buffer.
------------------------------------------ | | | | | | | | | LOCAL | MERGED | REMOTE | | | | | | | | | ------------------------------------------
layout = "MERGED"
Only the MERGED buffer will be shown. Note, however, that all the other ones are still loaded in vim, and you can access them with the "buffers" command.
------------------------------------------ | | | | | MERGED | | | | | ------------------------------------------
layout = "@LOCAL,REMOTE"
When MERGED is not present in the layout, you must "mark" one of the buffers with an arobase (@). That will become the buffer you need to edit and save after resolving the conflicts.
------------------------------------------ | | | | | | | | | | LOCAL | REMOTE | | | | | | | | | | ------------------------------------------
layout = "LOCAL,BASE,REMOTE / MERGED + BASE,LOCAL + BASE,REMOTE"
Three tabs will open: the first one is a copy of the default layout, while the other two only show the differences between (BASE and LOCAL) and (BASE and REMOTE) respectively.
------------------------------------------ | <TAB #1> | TAB #2 | TAB #3 | | ------------------------------------------ | | | | | LOCAL | BASE | REMOTE | | | | | ------------------------------------------ | | | MERGED | | | ------------------------------------------
------------------------------------------ | TAB #1 | <TAB #2> | TAB #3 | | ------------------------------------------ | | | | | | | | | | BASE | LOCAL | | | | | | | | | | ------------------------------------------
------------------------------------------ | TAB #1 | TAB #2 | <TAB #3> | | ------------------------------------------ | | | | | | | | | | BASE | REMOTE | | | | | | | | | | ------------------------------------------
layout = "LOCAL,BASE,REMOTE / MERGED + BASE,LOCAL + BASE,REMOTE + (LOCAL/BASE/REMOTE),MERGED"
Same as the previous example, but adds a fourth tab with the same information as the first tab, with a different layout.
--------------------------------------------- | TAB #1 | TAB #2 | TAB #3 | <TAB #4> | --------------------------------------------- | LOCAL | | |---------------------| | | BASE | MERGED | |---------------------| | | REMOTE | | ---------------------------------------------
Note how in the third tab definition we need to use parentheses to make , have precedence over /.
Instead of --tool=vimdiff, you can also use one of these other variants:
When using these variants, in order to specify a custom layout you will have to set configuration variables mergetool.gvimdiff.layout and mergetool.nvimdiff.layout instead of mergetool.vimdiff.layout (though the latter will be used as fallback if the variant-specific one is not set).
In addition, for backwards compatibility with previous Git versions, you can also append 1, 2 or 3 to either vimdiff or any of the variants (ex: vimdiff3, nvimdiff1, etc…) to use a predefined layout. In other words, using --tool=[g|n]vimdiff<x> is the same as using --tool=[g|n]vimdiff and setting configuration variable mergetool.[g|n]vimdiff.layout to…
Example: using --tool=gvimdiff2 will open gvim with three columns (LOCAL, MERGED and REMOTE).
Part of the the section called “git(1)” suite
Reads a tag's contents on standard input and creates a tag object. The output is the new tag's <object> identifier.
This command is mostly equivalent to the section called “git-hash-object(1)” invoked with -t tag -w --stdin. I.e. both of these will create and write a tag found in my-tag:
git mktag <my-tag git hash-object -t tag -w --stdin <my-tag
The difference is that mktag will die before writing the tag if the tag doesn't pass a the section called “git-fsck(1)” check.
The "fsck" check done by mktag is stricter than what the section called “git-fsck(1)” would run by default in that all fsck.<msg-id> messages are promoted from warnings to errors (so e.g. a missing "tagger" line is an error).
Extra headers in the object are also an error under mktag, but ignored by the section called “git-fsck(1)”. This extra check can be turned off by setting the appropriate fsck.<msg-id> variable:
git -c fsck.extraHeaderEntry=ignore mktag <my-tag-with-headers
A tag signature file, to be fed to this command's standard input, has a very simple fixed format: four lines of
object <hash> type <typename> tag <tagname> tagger <tagger>
followed by some optional free-form message (some tags created by older Git may not have a tagger line). The message, when it exists, is separated by a blank line from the header. The message part may contain a signature that Git itself doesn't care about, but that can be verified with gpg.
Part of the the section called “git(1)” suite
Reads standard input in non-recursive ls-tree output format, and creates a tree object. The order of the tree entries is normalized by mktree so pre-sorting the input is not required. The object name of the tree object built is written to the standard output.
Part of the the section called “git(1)” suite
gitmv[-v] [-f] [-n] [-k] <source> <destination>
gitmv[-v] [-f] [-n] [-k] <source>…<destination-directory>
Move or rename a file, directory, or symlink.
In the first form, it renames <source>, which must exist and be either a file, symlink or directory, to <destination>. In the second form, <destination-directory> has to be an existing directory; the given sources will be moved into this directory.
The index is updated after successful completion, but the change must still be committed.
Moving a submodule using a gitfile (which means they were cloned with a Git version 1.7.8 or newer) will update the gitfile and core.worktree setting to make the submodule work in the new location. It also will attempt to update the submodule.<name>.path setting in the the section called “gitmodules(5)” file and stage that file (unless -n is used).
Each time a superproject update moves a populated submodule (e.g. when switching between commits before and after the move) a stale submodule checkout will remain in the old location and an empty directory will appear in the new location. To populate the submodule again in the new location the user will have to run "git submodule update" afterwards. Removing the old directory is only safe when it uses a gitfile, as otherwise the history of the submodule will be deleted too. Both steps will be obsolete when recursive submodule update has been implemented.
Part of the the section called “git(1)” suite
Use given directory for the location of Git objects. We check <dir>/packs/multi-pack-index for the current MIDX file, and <dir>/packs for the pack-files to index.
<dir> must be an alternate of the current repository.
The following subcommands are available:
Write a new MIDX file. The following options are available for the write sub-command:
With --bitmap, optionally specify a file which contains a "refs snapshot" taken prior to repacking.
A reference snapshot is composed of line-delimited OIDs corresponding to the reference tips, usually taken by git repack prior to generating a new pack. A line may optionally start with a + character to indicate that the reference which corresponds to that OID is "preferred" (see the section called “git-config(1)”'s pack.preferBitmapTips.)
The file given at <path> is expected to be readable, and can contain duplicates. (If a given OID is given more than once, it is marked as preferred if at least one instance of it begins with the special + marker).
Delete the pack-files that are tracked by the MIDX file, but have no objects referenced by the MIDX (with the exception of .keep packs and cruft packs). Rewrite the MIDX file afterward to remove all references to these pack-files.
this mode is incompatible with incremental MIDX files.
Create a new pack-file containing objects in small pack-files referenced by the multi-pack-index. If the size given by the --batch-size=<size> argument is zero, then create a pack containing all objects referenced by the multi-pack-index. For a non-zero batch size, Select the pack-files by examining packs from oldest-to-newest, computing the "expected size" by counting the number of objects in the pack referenced by the multi-pack-index, then divide by the total number of objects in the pack and multiply by the pack size. We select packs with expected size below the batch size until the set of packs have total expected size at least the batch size, or all pack-files are considered. If only one pack-file is selected, then do nothing. If a new pack-file is created, rewrite the multi-pack-index to reference the new pack-file. A later run of git multi-pack-index expire will delete the pack-files that were part of this batch.
If repack.packKeptObjects is false, then any pack-files with an associated .keep file will not be selected for the batch to repack.
this mode is incompatible with incremental MIDX files.
Write a MIDX file for the packfiles in the current .git directory.
$ git multi-pack-index write
Write a MIDX file for the packfiles in the current .git directory with a corresponding bitmap.
$ git multi-pack-index write --preferred-pack=<pack> --bitmap
Write a MIDX file for the packfiles in an alternate object store.
$ git multi-pack-index --object-dir <alt> write
Verify the MIDX file for the packfiles in the current .git directory.
$ git multi-pack-index verify
See The Multi-Pack-Index Design Document and the section called “gitformat-pack(5)” for more information on the multi-pack-index feature and its file format.
Part of the the section called “git(1)” suite
Finds symbolic names suitable for human digestion for revisions given in any format parsable by git rev-parse.
Transform stdin by substituting all the 40-character SHA-1 hexes (say $hex) with "$hex ($rev_name)". When used with --name-only, substitute with "$rev_name", omitting $hex altogether. This option was called --stdin in older versions of Git.
For example:
$ cat sample.txt An abbreviated revision 2ae0a9cb82 will not be substituted. The full name after substitution is 2ae0a9cb8298185a94e5998086f380a355dd8907, while its tree object is 70d105cc79e63b81cfdcb08a15297c23e60b07ad $ git name-rev --annotate-stdin <sample.txt An abbreviated revision 2ae0a9cb82 will not be substituted. The full name after substitution is 2ae0a9cb8298185a94e5998086f380a355dd8907 (master), while its tree object is 70d105cc79e63b81cfdcb08a15297c23e60b07ad $ git name-rev --name-only --annotate-stdin <sample.txt An abbreviated revision 2ae0a9cb82 will not be substituted. The full name after substitution is master, while its tree object is 70d105cc79e63b81cfdcb08a15297c23e60b07ad
Given a commit, find out where it is relative to the local refs. Say somebody wrote you about that fantastic commit 33db5f4d9027a10e477ccf054b2c1ab94f74c85a. Of course, you look into the commit, but that only tells you what happened, but not the context.
Enter git name-rev:
% git name-rev 33db5f4d9027a10e477ccf054b2c1ab94f74c85a 33db5f4d9027a10e477ccf054b2c1ab94f74c85a tags/v0.99~940
Now you are wiser, because you know that it happened 940 revisions before v0.99.
Another nice thing you can do is:
% git log | git name-rev --annotate-stdin
Part of the the section called “git(1)” suite
gitnotes[list[<object>]]
gitnotesadd[-f] [--allow-empty] [--[no-]separator|--separator=<paragraph-break>] [--[no-]stripspace] [-F<file> |-m<msg> | (-c|-C) <object>] [-e] [<object>]
gitnotescopy[-f] (--stdin| <from-object> [<to-object>] )
gitnotesappend[--allow-empty] [--[no-]separator|--separator=<paragraph-break>] [--[no-]stripspace] [-F<file> |-m<msg> | (-c|-C) <object>] [-e] [<object>]
gitnotesedit[--allow-empty] [<object>] [--[no-]stripspace]
gitnotesshow[<object>]
gitnotesmerge[-v|-q] [-s<strategy> ] <notes-ref>
gitnotesmerge--commit[-v|-q]
gitnotesmerge--abort[-v|-q]
gitnotesremove[--ignore-missing] [--stdin] [<object>…]
gitnotesprune[-n] [-v]
gitnotesget-ref
Adds, removes, or reads notes attached to objects, without touching the objects themselves.
By default, notes are saved to and read from refs/notes/commits, but this default can be overridden. See the OPTIONS, CONFIGURATION, and ENVIRONMENT sections below. If this ref does not exist, it will be quietly created when it is first needed to store a note.
A typical use of notes is to supplement a commit message without changing the commit itself. Notes can be shown by git log along with the original commit message. To distinguish these notes from the message stored in the commit object, the notes are indented like the message, after an unindented line saying "Notes (<refname>):" (or "Notes:" for refs/notes/commits).
Notes can also be added to patches prepared with git format-patch by using the --notes option. Such notes are added as a patch commentary after a three dash separator line.
To change which notes are shown by git log, see the notes.displayRef discussion in CONFIGURATION.
See the notes.rewrite.<command> configuration for a way to carry notes across commands that rewrite commits.
Copy the notes for the first object onto the second object (defaults to HEAD). Abort if the second object already has notes, or if the first object has none (use -f to overwrite existing notes to the second object). This subcommand is equivalent to: git notes add [-f] -C $(git notes list <from-object>) <to-object>
In --stdin mode, take lines in the format
<from-object> SP <to-object> [ SP <rest> ] LF
on standard input, and copy the notes from each <from-object> to its corresponding <to-object>. (The optional <rest> is ignored so that the command can read the input given to the post-rewrite hook.)
--stdin cannot be combined with object names given on the command line.
Merge the given notes ref into the current notes ref. This will try to merge the changes made by the given notes ref (called "remote") since the merge-base (if any) into the current notes ref (called "local").
If conflicts arise and a strategy for automatically resolving conflicting notes (see the "NOTES MERGE STRATEGIES" section) is not given, the manual resolver is used. This resolver checks out the conflicting notes in a special worktree (.git/NOTES_MERGE_WORKTREE), and instructs the user to manually resolve the conflicts there. When done, the user can either finalize the merge with git notes merge --commit, or abort the merge with git notes merge --abort.
Remove the notes for given objects (defaults to HEAD). When giving zero or one object from the command line, this is equivalent to specifying an empty note message to the edit subcommand.
In --stdin mode, also remove the object names given on standard input. In other words, --stdin can be combined with object names from the command line.
Clean up whitespace. Specifically (see the section called “git-stripspace(1)”):
--stripspace is the default except for -C/--reuse-message. However, keep in mind that this depends on the order of similar options. For example, for -C <object> -m<message>, --stripspace will be used because the default for -m overrides the previous -C. This is a known limitation that may be fixed in the future.
Commit notes are blobs containing extra information about an object (usually information to supplement a commit's message). These blobs are taken from notes refs. A notes ref is usually a branch which contains "files" whose paths are the object names for the objects they describe, with some directory separators included for performance reasons [1].
Every notes change creates a new commit at the specified notes ref. You can therefore inspect the history of the notes by invoking, e.g., git log -p notes/commits. Currently the commit message only records which operation triggered the update, and the commit authorship is determined according to the usual rules (see the section called “git-commit(1)”). These details may change in the future.
It is also permitted for a notes ref to point directly to a tree object, in which case the history of the notes can be read with git log -p -g <refname>.
The default notes merge strategy is manual, which checks out conflicting notes in a special work tree for resolving notes conflicts (.git/NOTES_MERGE_WORKTREE), and instructs the user to resolve the conflicts in that work tree. When done, the user can either finalize the merge with git notes merge --commit, or abort the merge with git notes merge --abort.
Users may select an automated merge strategy from among the following using either -s/--strategy option or configuring notes.mergeStrategy accordingly:
ours automatically resolves conflicting notes in favor of the local version (i.e. the current notes ref).
theirs automatically resolves notes conflicts in favor of the remote version (i.e. the given notes ref being merged into the current notes ref).
union automatically resolves notes conflicts by concatenating the local and remote versions.
cat_sort_uniq is similar to union, but in addition to concatenating the local and remote versions, this strategy also sorts the resulting lines, and removes duplicate lines from the result. This is equivalent to applying the "cat | sort | uniq" shell pipeline to the local and remote versions. This strategy is useful if the notes follow a line-based format where one wants to avoid duplicated lines in the merge result. Note that if either the local or remote version contain duplicate lines prior to the merge, these will also be removed by this notes merge strategy.
You can use notes to add annotations with information that was not available at the time a commit was written.
$ git notes add -m 'Tested-by: Johannes Sixt <j6t@kdbg.org>' 72a144e2
$ git show -s 72a144e
[...]
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Notes:
Tested-by: Johannes Sixt <j6t@kdbg.org>In principle, a note is a regular Git blob, and any kind of (non-)format is accepted. You can binary-safely create notes from arbitrary files using git hash-object:
$ cc *.c $ blob=$(git hash-object -w a.out) $ git notes --ref=built add --allow-empty -C "$blob" HEAD
(You cannot simply use git notes --ref=built add -F a.out HEAD because that is not binary-safe.) Of course, it doesn't make much sense to display non-text-format notes with git log, so if you use such notes, you'll probably need to write some special-purpose tools to do something useful with them.
Everything above this line in this section isn't included from the the section called “git-config(1)” documentation. The content that follows is the same as what's found there:
Which merge strategy to choose by default when resolving notes conflicts. Must be one of manual, ours, theirs, union, or cat_sort_uniq. Defaults to manual. See the "NOTES MERGE STRATEGIES" section of the section called “git-notes(1)” for more information on each strategy.
This setting can be overridden by passing the --strategy option to the section called “git-notes(1)”.
Which ref (or refs, if a glob or specified more than once), in addition to the default set by core.notesRef or GIT_NOTES_REF, to read notes from when showing commit messages with the git log family of commands.
This setting can be overridden with the GIT_NOTES_DISPLAY_REF environment variable, which must be a colon separated list of refs or globs.
A warning will be issued for refs that do not exist, but a glob that does not match any refs is silently ignored.
This setting can be disabled by the --no-notes option to the the section called “git-log(1)” family of commands, or by the --notes=<ref> option accepted by those commands.
The effective value of core.notesRef (possibly overridden by GIT_NOTES_REF) is also implicitly added to the list of refs to be displayed.
When rewriting commits with <command> (currently amend or rebase), if this variable is false, git will not copy notes from the original to the rewritten commit. Defaults to true. See also notes.rewriteRef below.
This setting can be overridden with the GIT_NOTES_REWRITE_REF environment variable, which must be a colon separated list of refs or globs.
When copying notes during a rewrite (see the notes.rewrite.<command> option), determines what to do if the target commit already has a note. Must be one of overwrite, concatenate, cat_sort_uniq, or ignore. Defaults to concatenate.
This setting can be overridden with the GIT_NOTES_REWRITE_MODE environment variable.
When copying notes during a rewrite, specifies the (fully qualified) ref whose notes should be copied. May be a glob, in which case notes in all matching refs will be copied. You may also specify this configuration several times.
Does not have a default value; you must configure this variable to enable note rewriting. Set it to refs/notes/commits to enable rewriting for the default commit notes.
Can be overridden with the GIT_NOTES_REWRITE_REF environment variable. See notes.rewrite.<command> above for a further description of its format.
Colon-delimited list of refs or globs indicating which refs, in addition to the default from core.notesRef or GIT_NOTES_REF, to read notes from when showing commit messages. This overrides the notes.displayRef setting.
A warning will be issued for refs that do not exist, but a glob that does not match any refs is silently ignored.
When rewriting commits, which notes to copy from the original to the rewritten commit. Must be a colon-delimited list of refs or globs.
If not set in the environment, the list of notes to copy depends on the notes.rewrite.<command> and notes.rewriteRef settings.
Part of the the section called “git(1)” suite
git p4 clone [<sync-options>] [<clone-options>] <p4-depot-path>…
git p4 sync [<sync-options>] [<p4-depot-path>…]
git p4 rebase
git p4 submit [<submit-options>] [<master-branch-name>]
This command provides a way to interact with p4 repositories using Git.
Create a new Git repository from an existing p4 repository using git p4 clone, giving it one or more p4 depot paths. Incorporate new commits from p4 changes with git p4 sync. The sync command is also used to include new branches from other p4 depot paths. Submit Git changes back to p4 using git p4 submit. The command git p4 rebase does a sync plus rebases the current branch onto the updated p4 remote branch.
Clone a repository:
$ git p4 clone //depot/path/project
Do some work in the newly created Git repository:
$ cd project $ vi foo.h $ git commit -a -m "edited foo.h"
Update the Git repository with recent changes from p4, rebasing your work on top:
$ git p4 rebase
Submit your commits back to p4:
$ git p4 submit
Generally, git p4 clone is used to create a new Git directory from an existing p4 repository:
$ git p4 clone //depot/path/project
This:
To reproduce the entire p4 history in Git, use the @all modifier on the depot path:
$ git p4 clone //depot/path/project@all
As development continues in the p4 repository, those changes can be included in the Git repository using:
$ git p4 sync
This command finds new changes in p4 and imports them as Git commits.
P4 repositories can be added to an existing Git repository using git p4 sync too:
$ mkdir repo-git $ cd repo-git $ git init $ git p4 sync //path/in/your/perforce/depot
This imports the specified depot into refs/remotes/p4/master in an existing Git repository. The --branch option can be used to specify a different branch to be used for the p4 content.
If a Git repository includes branches refs/remotes/origin/p4, these will be fetched and consulted first during a git p4 sync. Since importing directly from p4 is considerably slower than pulling changes from a Git remote, this can be useful in a multi-developer environment.
If there are multiple branches, doing git p4 sync will automatically use the "BRANCH DETECTION" algorithm to try to partition new changes into the right branch. This can be overridden with the --branch option to specify just a single branch to update.
A common working pattern is to fetch the latest changes from the p4 depot and merge them with local uncommitted changes. Often, the p4 repository is the ultimate location for all code, thus a rebase workflow makes sense. This command does git p4 sync followed by git rebase to move local commits on top of updated p4 changes.
$ git p4 rebase
Submitting changes from a Git repository back to the p4 repository requires a separate p4 client workspace. This should be specified using the P4CLIENT environment variable or the Git configuration variable git-p4.client. The p4 client must exist, but the client root will be created and populated if it does not already exist.
To submit all changes that are in the current Git branch but not in the p4/master branch, use:
$ git p4 submit
To specify a branch other than the current one, use:
$ git p4 submit topicbranch
To specify a single commit or a range of commits, use:
$ git p4 submit --commit <sha1> $ git p4 submit --commit <sha1..sha1>
The upstream reference is generally refs/remotes/p4/master, but can be overridden using the --origin= command-line option.
The p4 changes will be created as the user invoking git p4 submit. The --preserve-user option will cause ownership to be modified according to the author of the Git commit. This option requires admin privileges in p4, which can be granted using p4 protect.
To shelve changes instead of submitting, use --shelve and --update-shelve:
$ git p4 submit --shelve $ git p4 submit --update-shelve 1234 --update-shelve 2345
Unshelving will take a shelved P4 changelist, and produce the equivalent git commit in the branch refs/remotes/p4-unshelved/<changelist>.
The git commit is created relative to the current origin revision (HEAD by default). A parent commit is created based on the origin, and then the unshelve commit is created based on that.
The origin revision can be changed with the "--origin" option.
If the target branch in refs/remotes/p4-unshelved already exists, the old one will be renamed.
$ git p4 sync $ git p4 unshelve 12345 $ git show p4-unshelved/12345 <submit more changes via p4 to the same files> $ git p4 unshelve 12345 <refuses to unshelve until git is in sync with p4 again>
All commands except clone accept these options.
These options can be used in the initial clone as well as in subsequent sync operations.
Import changes into <ref> instead of refs/remotes/p4/master. If <ref> starts with refs/, it is used as is. Otherwise, if it does not start with p4/, that prefix is added.
By default a <ref> not starting with refs/ is treated as the name of a remote-tracking branch (under refs/remotes/). This behavior can be modified using the --import-local option.
The default <ref> is "master".
This example imports a new remote "p4/proj2" into an existing Git repository:
$ git init
$ git p4 sync --branch=refs/remotes/p4/proj2 //depot/proj2These options can be used in an initial clone, along with the sync options described above.
These options can be used to modify git p4 submit behavior.
The p4-pre-submit hook is executed if it exists and is executable. The hook takes no parameters and nothing from standard input. Exiting with non-zero status from this script prevents git-p4 submit from launching. It can be bypassed with the --no-verify command line option.
One usage scenario is to run unit tests in the hook.
The p4-prepare-changelist hook is executed right after preparing the default changelist message and before the editor is started. It takes one parameter, the name of the file that contains the changelist text. Exiting with a non-zero status from the script will abort the process.
The purpose of the hook is to edit the message file in place, and it is not suppressed by the --no-verify option. This hook is called even if --prepare-p4-only is set.
The p4-changelist hook is executed after the changelist message has been edited by the user. It can be bypassed with the --no-verify option. It takes a single parameter, the name of the file that holds the proposed changelist text. Exiting with a non-zero status causes the command to abort.
The hook is allowed to edit the changelist file and can be used to normalize the text into some project standard format. It can also be used to refuse the Submit after inspect the message file.
The p4-post-changelist hook is invoked after the submit has successfully occurred in P4. It takes no parameters and is meant primarily for notification and cannot affect the outcome of the git p4 submit action.
These options can be used to modify git p4 rebase behavior.
The p4 depot path argument to git p4 sync and git p4 clone can be one or more space-separated p4 depot paths, with an optional p4 revision specifier on the end:
See p4 help revisions for the full syntax of p4 revision specifiers.
The p4 client specification is maintained with the p4 client command and contains among other fields, a View that specifies how the depot is mapped into the client repository. The clone and sync commands can consult the client spec when given the --use-client-spec option or when the useClientSpec variable is true. After git p4 clone, the useClientSpec variable is automatically set in the repository configuration file. This allows future git p4 submit commands to work properly; the submit command looks only at the variable and does not have a command-line option.
The full syntax for a p4 view is documented in p4 help views. git p4 knows only a subset of the view syntax. It understands multi-line mappings, overlays with +, exclusions with - and double-quotes around whitespace. Of the possible wildcards, git p4 only handles …, and only when it is at the end of the path. git p4 will complain if it encounters an unhandled wildcard.
Bugs in the implementation of overlap mappings exist. If multiple depot paths map through overlays to the same location in the repository, git p4 can choose the wrong one. This is hard to solve without dedicating a client spec just for git p4.
The name of the client can be given to git p4 in multiple ways. The variable git-p4.client takes precedence if it exists. Otherwise, normal p4 mechanisms of determining the client are used: environment variable P4CLIENT, a file referenced by P4CONFIG, or the local host name.
P4 does not have the same concept of a branch as Git. Instead, p4 organizes its content as a directory tree, where by convention different logical branches are in different locations in the tree. The p4 branch command is used to maintain mappings between different areas in the tree, and indicate related content. git p4 can use these mappings to determine branch relationships.
If you have a repository where all the branches of interest exist as subdirectories of a single depot path, you can use --detect-branches when cloning or syncing to have git p4 automatically find subdirectories in p4, and to generate these as branches in Git.
For example, if the P4 repository structure is:
//depot/main/... //depot/branch1/...
And "p4 branch -o branch1" shows a View line that looks like:
//depot/main/... //depot/branch1/...
Then this git p4 clone command:
git p4 clone --detect-branches //depot@all
produces a separate branch in refs/remotes/p4/ for //depot/main, called master, and one for //depot/branch1 called depot/branch1.
However, it is not necessary to create branches in p4 to be able to use them like branches. Because it is difficult to infer branch relationships automatically, a Git configuration setting git-p4.branchList can be used to explicitly identify branch relationships. It is a list of "source:destination" pairs, like a simple p4 branch specification, where the "source" and "destination" are the path elements in the p4 repository. The example above relied on the presence of the p4 branch. Without p4 branches, the same result will occur with:
git init depot cd depot git config git-p4.branchList main:branch1 git p4 clone --detect-branches //depot@all .
The fast-import mechanism used by git p4 creates one pack file for each invocation of git p4 sync. Normally, Git garbage compression (the section called “git-gc(1)”) automatically compresses these to fewer pack files, but explicit invocation of git repack -adf may improve performance.
The following config settings can be used to modify git p4 behavior. They all are in the git-p4 section.
List of branches to be imported when branch detection is enabled. Each entry should be a pair of branch names separated by a colon (:). This example declares that both branchA and branchB were created from main:
git config git-p4.branchList main:branchA git config --add git-p4.branchList main:branchB
Specify the system that is used for large (binary) files. Please note that large file systems do not support the git p4 submit command. Only Git LFS is implemented right now (see https://git-lfs.github.com/ for more information). Download and install the Git LFS command line extension to use this option and configure it like this:
git config git-p4.largeFileSystem GitLFS
Map a P4 user to a name and email address in Git. Use a string with the following format to create a mapping:
git config --add git-p4.mapUser "p4user = First Last <mail@address.com>"
A mapping will override any user information from P4. Mappings for multiple P4 user can be defined.
Part of the the section called “git(1)” suite
git pack-objects [-q | --progress | --all-progress] [--all-progress-implied]
[--no-reuse-delta] [--delta-base-offset] [--non-empty]
[--local] [--incremental] [--window=<n>] [--depth=<n>]
[--revs [--unpacked | --all]] [--keep-pack=<pack-name>]
[--cruft] [--cruft-expiration=<time>]
[--stdout [--filter=<filter-spec>] | <base-name>]
[--shallow] [--keep-true-parents] [--[no-]sparse]
[--name-hash-version=<n>] < <object-list>
Reads list of objects from the standard input, and writes either one or more packed archives with the specified base-name to disk, or a packed archive to the standard output.
A packed archive is an efficient way to transfer a set of objects between two repositories as well as an access efficient archival format. In a packed archive, an object is either stored as a compressed whole or as a difference from some other object. The latter is often called a delta.
The packed archive format (.pack) is designed to be self-contained so that it can be unpacked without any further information. Therefore, each object that a delta depends upon must be present within the pack.
A pack index file (.idx) is generated for fast, random access to the objects in the pack. Placing both the index file (.idx) and the packed archive (.pack) in the pack/ subdirectory of $GIT_OBJECT_DIRECTORY (or any of the directories on $GIT_ALTERNATE_OBJECT_DIRECTORIES) enables Git to read from the pack archive.
The git unpack-objects command can read the packed archive and expand the objects contained in the pack into "one-file one-object" format; this is typically done by the smart-pull commands when a pack is created on-the-fly for efficient network transport by their peers.
Read the basenames of packfiles (e.g., pack-1234abcd.pack) from the standard input, instead of object names or revision arguments. The resulting pack contains all objects listed in the included packs (those not beginning with ^), excluding any objects listed in the excluded packs (beginning with ^).
Incompatible with --revs, or options that imply --revs (such as --all), with the exception of --unpacked, which is compatible.
Packs unreachable objects into a separate "cruft" pack, denoted by the existence of a .mtimes file. Typically used by git repack --cruft. Callers provide a list of pack names and indicate which packs will remain in the repository, along with which packs will be deleted (indicated by the - prefix). The contents of the cruft pack are all objects not contained in the surviving packs which have not exceeded the grace period (see --cruft-expiration below), or which have exceeded the grace period, but are reachable from an other object which hasn't.
When the input lists a pack containing all reachable objects (and lists all other packs as pending deletion), the corresponding cruft pack will contain all unreachable objects (with mtime newer than the --cruft-expiration) along with any unreachable objects whose mtime is older than the --cruft-expiration, but are reachable from an unreachable object whose mtime is newer than the --cruft-expiration).
Incompatible with --unpack-unreachable, --keep-unreachable, --pack-loose-unreachable, --stdin-packs, as well as any other options which imply --revs.
These two options affect how the objects contained in the pack are stored using delta compression. The objects are first internally sorted by type, size and optionally names and compared against the other objects within --window to see if using delta compression saves space. --depth limits the maximum delta depth; making it too deep affects the performance on the unpacker side, because delta data needs to be applied that many times to get to the necessary object.
The default value for --window is 10 and --depth is 50. The maximum depth is 4095.
Create a "thin" pack by omitting the common objects between a sender and a receiver in order to reduce network transfer. This option only makes sense in conjunction with --stdout.
Note: A thin pack violates the packed archive format by omitting required objects and is thus unusable by Git without making it self-contained. Use git index-pack --fix-thin (see the section called “git-index-pack(1)”) to restore the self-contained property.
A packed archive can express the base object of a delta as either a 20-byte object name or as an offset in the stream, but ancient versions of Git don't understand the latter. By default, git pack-objects only uses the former format for better compatibility. This option allows the command to use the latter format for compactness. Depending on the average delta chain length, this option typically shrinks the resulting packfile by 3-5 per-cent.
Note: Porcelain commands such as git gc (see the section called “git-gc(1)”), git repack (see the section called “git-repack(1)”) pass this option by default in modern Git when they put objects in your repository into pack files. So does git bundle (see the section called “git-bundle(1)”) when it creates a bundle.
A debug option to help with future "partial clone" development. This option specifies how missing objects are handled.
The form --missing=error requests that pack-objects stop with an error if a missing object is encountered. If the repository is a partial clone, an attempt to fetch missing objects will be made before declaring them missing. This is the default action.
The form --missing=allow-any will allow object traversal to continue if a missing object is encountered. No fetch of a missing object will occur. Missing objects will silently be omitted from the results.
The form --missing=allow-promisor is like allow-any, but will only allow object traversal to continue for EXPECTED promisor missing objects. No fetch of a missing object will occur. An unexpected missing object will raise an error.
While performing delta compression, Git groups objects that may be similar based on heuristics using the path to that object. While grouping objects by an exact path match is good for paths with many versions, there are benefits for finding delta pairs across different full paths. Git collects objects by type and then by a "name hash" of the path and then by size, hoping to group objects that will compress well together.
The default name hash version is 1, which prioritizes hash locality by considering the final bytes of the path as providing the maximum magnitude to the hash function. This version excels at distinguishing short paths and finding renames across directories. However, the hash function depends primarily on the final 16 bytes of the path. If there are many paths in the repo that have the same final 16 bytes and differ only by parent directory, then this name-hash may lead to too many collisions and cause poor results. At the moment, this version is required when writing reachability bitmap files with --write-bitmap-index.
The name hash version 2 has similar locality features as version 1, except it considers each path component separately and overlays the hashes with a shift. This still prioritizes the final bytes of the path, but also "salts" the lower bits of the hash using the parent directory names. This method allows for some of the locality benefits of version 1 while breaking most of the collisions from a similarly-named file appearing in many different directories. At the moment, this version is not allowed when writing reachability bitmap files with --write-bitmap-index and it will be automatically changed to version 1.
When possible, pack-objects tries to reuse existing on-disk deltas to avoid having to search for new ones on the fly. This is an important optimization for serving fetches, because it means the server can avoid inflating most objects at all and just send the bytes directly from disk. This optimization can't work when an object is stored as a delta against a base which the receiver does not have (and which we are not already sending). In that case the server "breaks" the delta and has to find a new one, which has a high CPU cost. Therefore it's important for performance that the set of objects in on-disk delta relationships match what a client would fetch.
In a normal repository, this tends to work automatically. The objects are mostly reachable from the branches and tags, and that's what clients fetch. Any deltas we find on the server are likely to be between objects the client has or will have.
But in some repository setups, you may have several related but separate groups of ref tips, with clients tending to fetch those groups independently. For example, imagine that you are hosting several "forks" of a repository in a single shared object store, and letting clients view them as separate repositories through GIT_NAMESPACE or separate repos using the alternates mechanism. A naive repack may find that the optimal delta for an object is against a base that is only found in another fork. But when a client fetches, they will not have the base object, and we'll have to find a new delta on the fly.
A similar situation may exist if you have many refs outside of refs/heads/ and refs/tags/ that point to related objects (e.g., refs/pull or refs/changes used by some hosting providers). By default, clients fetch only heads and tags, and deltas against objects found only in those other groups cannot be sent as-is.
Delta islands solve this problem by allowing you to group your refs into distinct "islands". Pack-objects computes which objects are reachable from which islands, and refuses to make a delta from an object A against a base which is not present in all of A's islands. This results in slightly larger packs (because we miss some delta opportunities), but guarantees that a fetch of one island will not have to recompute deltas on the fly due to crossing island boundaries.
When repacking with delta islands the delta window tends to get clogged with candidates that are forbidden by the config. Repacking with a big --window helps (and doesn't take as long as it otherwise might because we can reject some object pairs based on islands before doing any computation on the content).
Islands are configured via the pack.island option, which can be specified multiple times. Each value is a left-anchored regular expressions matching refnames. For example:
[pack] island = refs/heads/ island = refs/tags/
puts heads and tags into an island (whose name is the empty string; see below for more on naming). Any refs which do not match those regular expressions (e.g., refs/pull/123) is not in any island. Any object which is reachable only from refs/pull/ (but not heads or tags) is therefore not a candidate to be used as a base for refs/heads/.
Refs are grouped into islands based on their "names", and two regexes that produce the same name are considered to be in the same island. The names are computed from the regexes by concatenating any capture groups from the regex, with a - dash in between. (And if there are no capture groups, then the name is the empty string, as in the above example.) This allows you to create arbitrary numbers of islands. Only up to 14 such capture groups are supported though.
For example, imagine you store the refs for each fork in refs/virtual/ID, where ID is a numeric identifier. You might then configure:
[pack] island = refs/virtual/([0-9]+)/heads/ island = refs/virtual/([0-9]+)/tags/ island = refs/virtual/([0-9]+)/(pull)/
That puts the heads and tags for each fork in their own island (named "1234" or similar), and the pull refs for each go into their own "1234-pull".
Note that we pick a single island for each regex to go into, using "last one wins" ordering (which allows repo-specific config to take precedence over user-wide config, and so forth).
Various configuration variables affect packing, see the section called “git-config(1)” (search for "pack" and "delta").
Notably, delta compression is not used on objects larger than the core.bigFileThreshold configuration variable and on files with the attribute delta set to false.
the section called “git-rev-list(1)” the section called “git-repack(1)” the section called “git-prune-packed(1)”
Part of the the section called “git(1)” suite
git pack-redundant has been deprecated and is scheduled for removal in a future version of Git. Because it can only remove entire duplicate packs and not individual duplicate objects, it is generally not a useful tool for reducing repository size. You are better off using git gc to do so, which will put objects into a new pack, removing duplicates.
Running pack-redundant without the --i-still-use-this flag will fail in this release. If you believe you have a use case for which pack-redundant is better suited and oppose this removal, please contact the Git mailing list at git@vger.kernel.org. More information about the list is available at https://git-scm.com/community.
This program computes which packs in your repository are redundant. The output is suitable for piping to xargs rm if you are in the root of the repository.
git pack-redundant accepts a list of objects on standard input. Any objects given will be ignored when checking which packs are required. This makes the following command useful when wanting to remove packs which contain unreachable objects.
git fsck --full --unreachable | cut -d ' ' -f3 | \ git pack-redundant --all | xargs rm
the section called “git-pack-objects(1)” the section called “git-repack(1)” the section called “git-prune-packed(1)”
Part of the the section called “git(1)” suite
Traditionally, tips of branches and tags (collectively known as refs) were stored one file per ref in a (sub)directory under $GIT_DIR/refs directory. While many branch tips tend to be updated often, most tags and some branch tips are never updated. When a repository has hundreds or thousands of tags, this one-file-per-ref format both wastes storage and hurts performance.
This command is used to solve the storage and performance problem by storing the refs in a single file, $GIT_DIR/packed-refs. When a ref is missing from the traditional $GIT_DIR/refs directory hierarchy, it is looked up in this file and used if found.
Subsequent updates to branches always create new files under $GIT_DIR/refs directory hierarchy.
A recommended practice to deal with a repository with too many refs is to pack its refs with --all once, and occasionally run git pack-refs. Tags are by definition stationary and are not expected to change. Branch heads will be packed with the initial pack-refs --all, but only the currently active branch heads will become unpacked, and the next pack-refs (without --all) will leave them unpacked.
Pack refs as needed depending on the current state of the ref database. The behavior depends on the ref format used by the repository and may change in the future.
Do not pack refs matching the given glob(7) pattern. Repetitions of this option accumulate exclusion patterns. Use --no-exclude to clear and reset the list of patterns. If a ref is already packed, including it with --exclude will not unpack it.
When used with --all, pack only loose refs which do not match any of the provided --exclude patterns.
When used with --include, refs provided to --include, minus refs that are provided to --exclude will be packed.
Older documentation written before the packed-refs mechanism was introduced may still say things like ".git/refs/heads/<branch> file exists" when it means "branch <branch> exists".
Part of the the section called “git(1)” suite
Read a patch from the standard input and compute the patch ID for it.
A "patch ID" is nothing but a sum of SHA-1 of the file diffs associated with a patch, with line numbers ignored. As such, it's "reasonably stable", but at the same time also reasonably unique, i.e., two patches that have the same "patch ID" are almost guaranteed to be the same thing.
The main usecase for this command is to look for likely duplicate commits.
When dealing with git diff-tree output, it takes advantage of the fact that the patch is prefixed with the object name of the commit, and outputs two 40-byte hexadecimal strings. The first string is the patch ID, and the second string is the commit ID. This can be used to make a mapping from patch ID to commit ID.
Calculate the patch-id of the input as it is given, do not strip any whitespace.
This is the default if patchid.verbatim is true.
Use a "stable" sum of hashes as the patch ID. With this option:
All whitespace within the patch is ignored and does not affect the id.
This is the default if patchid.stable is set to true.
Use an "unstable" hash as the patch ID. With this option, the result produced is compatible with the patch-id value produced by git 1.9 and older and whitespace is ignored. Users with pre-existing databases storing patch-ids produced by git 1.9 and older (who do not deal with reordered patches) may want to use this option.
This is the default.
Part of the the section called “git(1)” suite
This program searches the $GIT_OBJECT_DIRECTORY for all objects that currently exist in a pack file as well as in the independent object directories.
All such extra objects are removed.
A pack is a collection of objects, individually compressed, with delta compression applied, stored in a single file, with an associated index file.
Packs are used to reduce the load on mirror systems, backup engines, disk storage, etc.
Part of the the section called “git(1)” suite
In most cases, users should run git gc, which calls git prune. See the section "NOTES", below.
This runs git fsck --unreachable using all the refs available in refs/, optionally with an additional set of objects specified on the command line, and prunes all unpacked objects unreachable from any of these head objects from the object database. In addition, it prunes the unpacked objects that are also found in packs by running git prune-packed. It also removes entries from .git/shallow that are not reachable by any ref.
Note that unreachable, packed objects will remain. If this is not desired, see the section called “git-repack(1)”.
To prune objects not used by your repository or another that borrows from your repository via its .git/objects/info/alternates:
$ git prune $(cd ../another && git rev-parse --all)
In most cases, users will not need to call git prune directly, but should instead call git gc, which handles pruning along with many other housekeeping tasks.
For a description of which objects are considered for pruning, see git fsck's --unreachable option.
the section called “git-fsck(1)”, the section called “git-gc(1)”, the section called “git-reflog(1)”
Part of the the section called “git(1)” suite
Incorporates changes from a remote repository into the current branch. If the current branch is behind the remote, then by default it will fast-forward the current branch to match the remote. If the current branch and the remote have diverged, the user needs to specify how to reconcile the divergent branches with --rebase or --no-rebase (or the corresponding configuration option in pull.rebase).
More precisely, git pull runs git fetch with the given parameters and then depending on configuration options or command line flags, will call either git rebase or git merge to reconcile diverging branches.
<repository> should be the name of a remote repository as passed to the section called “git-fetch(1)”. <refspec> can name an arbitrary remote ref (for example, the name of a tag) or even a collection of refs with corresponding remote-tracking branches (e.g., refs/heads/*:refs/remotes/origin/*), but usually it is the name of a branch in the remote repository.
Default values for <repository> and <branch> are read from the "remote" and "merge" configuration for the current branch as set by the section called “git-branch(1)” --track.
Assume the following history exists and the current branch is "master":
A---B---C master on origin
/
D---E---F---G master
^
origin/master in your repositoryThen "git pull" will fetch and replay the changes from the remote master branch since it diverged from the local master (i.e., E) until its current commit (C) on top of master and record the result in a new commit along with the names of the two parent commits and a log message from the user describing the changes.
A---B---C origin/master
/ \
D---E---F---G---H masterSee the section called “git-merge(1)” for details, including how conflicts are presented and handled.
In Git 1.7.0 or later, to cancel a conflicting merge, use git reset --merge. Warning: In older versions of Git, running git pull with uncommitted changes is discouraged: while possible, it leaves you in a state that may be hard to back out of in the case of a conflict.
If any of the remote changes overlap with local uncommitted changes, the merge will be automatically canceled and the work tree untouched. It is generally best to get any local changes in working order before pulling or stash them away with the section called “git-stash(1)”.
This option controls if new commits of populated submodules should be fetched, and if the working trees of active submodules should be updated, too (see the section called “git-fetch(1)”, the section called “git-config(1)” and the section called “gitmodules(5)”).
If the checkout is done via rebase, local submodule commits are rebased as well.
If the update is done via merge, the submodule conflicts are resolved and checked out.
Perform the merge and commit the result. This option can be used to override --no-commit. Only useful when merging.
With --no-commit perform the merge and stop just before creating a merge commit, to give the user a chance to inspect and further tweak the merge result before committing.
Note that fast-forward updates do not create a merge commit and therefore there is no way to stop those merges with --no-commit. Thus, if you want to ensure your branch is not changed or updated by the merge command, use --no-ff with --no-commit.
Invoke an editor before committing successful mechanical merge to further edit the auto-generated merge message, so that the user can explain and justify the merge. The --no-edit option can be used to accept the auto-generated message (this is generally discouraged).
Older scripts may depend on the historical behaviour of not allowing the user to edit the merge log message. They will see an editor opened when they run git merge. To make it easier to adjust such scripts to the updated behaviour, the environment variable GIT_MERGE_AUTOEDIT can be set to no at the beginning of them.
When merging rather than rebasing, specifies how a merge is handled when the merged-in history is already a descendant of the current history. If merging is requested, --ff is the default unless merging an annotated (and possibly signed) tag that is not stored in its natural place in the refs/tags/ hierarchy, in which case --no-ff is assumed.
With --ff, when possible resolve the merge as a fast-forward (only update the branch pointer to match the merged branch; do not create a merge commit). When not possible (when the merged-in history is not a descendant of the current history), create a merge commit.
With --no-ff, create a merge commit in all cases, even when the merge could instead be resolved as a fast-forward.
In addition to branch names, populate the log message with one-line descriptions from at most <n> actual commits that are being merged. See also the section called “git-fmt-merge-msg(1)”. Only useful when merging.
With --no-log do not list one-line descriptions from the actual commits being merged.
Add a Signed-off-by trailer by the committer at the end of the commit log message. The meaning of a signoff depends on the project to which you're committing. For example, it may certify that the committer has the rights to submit the work under the project's license or agrees to some contributor representation, such as a Developer Certificate of Origin. (See https://developercertificate.org for the one used by the Linux kernel and Git projects.) Consult the documentation or leadership of the project to which you're contributing to understand how the signoffs are used in that project.
The --no-signoff option can be used to countermand an earlier --signoff option on the command line.
Show a diffstat at the end of the merge. The diffstat is also controlled by the configuration option merge.stat.
With -n or --no-stat do not show a diffstat at the end of the merge.
Produce the working tree and index state as if a real merge happened (except for the merge information), but do not actually make a commit, move the HEAD, or record $GIT_DIR/MERGE_HEAD (to cause the next git commit command to create a merge commit). This allows you to create a single commit on top of the current branch whose effect is the same as merging another branch (or more in case of an octopus).
With --no-squash perform the merge and commit the result. This option can be used to override --squash.
With --squash, --commit is not allowed, and will fail.
Only useful when merging.
Verify that the tip commit of the side branch being merged is signed with a valid key, i.e. a key that has a valid uid: in the default trust model, this means the signing key has been signed by a trusted key. If the tip commit of the side branch is not signed with a valid key, the merge is aborted.
Only useful when merging.
By default, git merge command refuses to merge histories that do not share a common ancestor. This option can be used to override this safety when merging histories of two projects that started their lives independently. As that is a very rare occasion, no configuration variable to enable this by default exists or will be added.
Only useful when merging.
When true, rebase the current branch on top of the upstream branch after fetching. If there is a remote-tracking branch corresponding to the upstream branch and the upstream branch was rebased since last fetched, the rebase uses that information to avoid rebasing non-local changes.
When set to merges, rebase using git rebase --rebase-merges so that the local merge commits are included in the rebase (see the section called “git-rebase(1)” for details).
When false, merge the upstream branch into the current branch.
When interactive, enable the interactive mode of rebase.
See pull.rebase, branch.<name>.rebase and branch.autoSetupRebase in the section called “git-config(1)” if you want to make git pull always use --rebase instead of merging.
This is a potentially dangerous mode of operation. It rewrites history, which does not bode well when you published that history already. Do not use this option unless you have read the section called “git-rebase(1)” carefully.
If the source repository is complete, convert a shallow repository to a complete one, removing all the limitations imposed by shallow repositories.
If the source repository is shallow, fetch as much as possible so that the current repository has the same history as the source repository.
By default, Git will report, to the server, commits reachable from all local refs to find common commits in an attempt to reduce the size of the to-be-received packfile. If specified, Git will only report commits reachable from the given tips. This is useful to speed up fetches when the user knows which local ref is likely to have commits in common with the upstream ref being fetched.
This option may be specified more than once; if so, Git will report commits reachable from any of the given commits.
The argument to this option may be a glob on ref names, a ref, or the (possibly abbreviated) SHA-1 of a commit. Specifying a glob is equivalent to specifying this option multiple times, one for each matching ref name.
See also the fetch.negotiationAlgorithm and push.negotiate configuration variables documented in the section called “git-config(1)”, and the --negotiate-only option below.
Do not fetch anything from the server, and instead print the ancestors of the provided --negotiation-tip=* arguments, which we have in common with the server.
This is incompatible with --recurse-submodules=[yes|on-demand]. Internally this is used to implement the push.negotiate option, see the section called “git-config(1)”.
Print the output to standard output in an easy-to-parse format for scripts. See section OUTPUT in the section called “git-fetch(1)” for details.
This is incompatible with --recurse-submodules=[yes|on-demand] and takes precedence over the fetch.output config option.
Number of parallel children to be used for all forms of fetching.
If the --multiple option was specified, the different remotes will be fetched in parallel. If multiple submodules are fetched, they will be fetched in parallel. To control them independently, use the config settings fetch.parallel and submodule.fetchJobs (see the section called “git-config(1)”).
Typically, parallel recursive and multi-remote fetches will be faster. By default fetches are performed sequentially, not in parallel.
Specifies which refs to fetch and which local refs to update. When no <refspec>s appear on the command line, the refs to fetch are read from remote.<repository>.fetch variables instead (see the section "CONFIGURED REMOTE-TRACKING BRANCHES" in the section called “git-fetch(1)”).
The format of a <refspec> parameter is an optional plus +, followed by the source <src>, followed by a colon :, followed by the destination <dst>. The colon can be omitted when <dst> is empty. <src> is typically a ref, or a glob pattern with a single * that is used to match a set of refs, but it can also be a fully spelled hex object name.
A <refspec> may contain a * in its <src> to indicate a simple pattern match. Such a refspec functions like a glob that matches any ref with the pattern. A pattern <refspec> must have one and only one * in both the <src> and <dst>. It will map refs to the destination by replacing the * with the contents matched from the source.
If a refspec is prefixed by ^, it will be interpreted as a negative refspec. Rather than specifying which refs to fetch or which local refs to update, such a refspec will instead specify refs to exclude. A ref will be considered to match if it matches at least one positive refspec, and does not match any negative refspec. Negative refspecs can be useful to restrict the scope of a pattern refspec so that it will not include specific refs. Negative refspecs can themselves be pattern refspecs. However, they may only contain a <src> and do not specify a <dst>. Fully spelled out hex object names are also not supported.
tag <tag> means the same as refs/tags/<tag>:refs/tags/<tag>; it requests fetching everything up to the given tag.
The remote ref that matches <src> is fetched, and if <dst> is not an empty string, an attempt is made to update the local ref that matches it.
Whether that update is allowed without --force depends on the ref namespace it's being fetched to, the type of object being fetched, and whether the update is considered to be a fast-forward. Generally, the same rules apply for fetching as when pushing, see the <refspec>... section of the section called “git-push(1)” for what those are. Exceptions to those rules particular to git fetch are noted below.
Until Git version 2.20, and unlike when pushing with the section called “git-push(1)”, any updates to refs/tags/* would be accepted without + in the refspec (or --force). When fetching, we promiscuously considered all tag updates from a remote to be forced fetches. Since Git version 2.20, fetching to update refs/tags/* works the same way as when pushing. I.e. any updates will be rejected without + in the refspec (or --force).
Unlike when pushing with the section called “git-push(1)”, any updates outside of refs/{tags,heads}/* will be accepted without + in the refspec (or --force), whether that's swapping e.g. a tree object for a blob, or a commit for another commit that doesn't have the previous commit as an ancestor etc.
Unlike when pushing with the section called “git-push(1)”, there is no configuration which'll amend these rules, and nothing like a pre-fetch hook analogous to the pre-receive hook.
As with pushing with the section called “git-push(1)”, all of the rules described above about what's not allowed as an update can be overridden by adding an optional leading + to a refspec (or using the --force command line option). The only exception to this is that no amount of forcing will make the refs/heads/* namespace accept a non-commit object.
When the remote branch you want to fetch is known to be rewound and rebased regularly, it is expected that its new tip will not be a descendant of its previous tip (as stored in your remote-tracking branch the last time you fetched). You would want to use the + sign to indicate non-fast-forward updates will be needed for such branches. There is no way to determine or declare that a branch will be made available in a repository with this behavior; the pulling user simply must know this is the expected usage pattern for a branch.
There is a difference between listing multiple <refspec> directly on git pull command line and having multiple remote.<repository>.fetch entries in your configuration for a <repository> and running a git pull command without any explicit <refspec> parameters. <refspec>s listed explicitly on the command line are always merged into the current branch after fetching. In other words, if you list more than one remote ref, git pull will create an Octopus merge. On the other hand, if you do not list any explicit <refspec> parameter on the command line, git pull will fetch all the <refspec>s it finds in the remote.<repository>.fetch configuration and merge only the first <refspec> found into the current branch. This is because making an Octopus from remote refs is rarely done, while keeping track of multiple remote heads in one-go by fetching more than one is often useful.
In general, URLs contain information about the transport protocol, the address of the remote server, and the path to the repository. Depending on the transport protocol, some of this information may be absent.
Git supports ssh, git, http, and https protocols (in addition, ftp and ftps can be used for fetching, but this is inefficient and deprecated; do not use them).
The native transport (i.e. git:// URL) does no authentication and should be used with caution on unsecured networks.
The following syntaxes may be used with them:
An alternative scp-like syntax may also be used with the ssh protocol:
This syntax is only recognized if there are no slashes before the first colon. This helps differentiate a local path that contains a colon. For example the local path foo:bar could be specified as an absolute path or ./foo:bar to avoid being misinterpreted as an ssh url.
The ssh and git protocols additionally support ~<username> expansion:
For local repositories, also supported by Git natively, the following syntaxes may be used:
These two syntaxes are mostly equivalent, except when cloning, when the former implies --local option. See the section called “git-clone(1)” for details.
git clone, git fetch and git pull, but not git push, will also accept a suitable bundle file. See the section called “git-bundle(1)”.
When Git doesn't know how to handle a certain transport protocol, it attempts to use the remote-<transport> remote helper, if one exists. To explicitly request a remote helper, the following syntax may be used:
where <address> may be a path, a server and path, or an arbitrary URL-like string recognized by the specific remote helper being invoked. See the section called “gitremote-helpers(7)” for details.
If there are a large number of similarly-named remote repositories and you want to use a different format for them (such that the URLs you use will be rewritten into URLs that work), you can create a configuration section of the form:
[url "<actual-url-base>"]
insteadOf = <other-url-base>
For example, with this:
[url "git://git.host.xz/"]
insteadOf = host.xz:/path/to/
insteadOf = work:a URL like "work:repo.git" or like "host.xz:/path/to/repo.git" will be rewritten in any context that takes a URL to be "git://git.host.xz/repo.git".
If you want to rewrite URLs for push only, you can create a configuration section of the form:
[url "<actual-url-base>"]
pushInsteadOf = <other-url-base>
For example, with this:
[url "ssh://example.org/"]
pushInsteadOf = git://example.org/a URL like "git://example.org/path/to/repo.git" will be rewritten to "ssh://example.org/path/to/repo.git" for pushes, but pulls will still use the original URL.
The name of one of the following can be used instead of a URL as <repository> argument:
All of these also allow you to omit the refspec from the command line because they each contain a refspec which git will use by default.
You can choose to provide the name of a remote which you had previously configured using the section called “git-remote(1)”, the section called “git-config(1)” or even by a manual edit to the $GIT_DIR/config file. The URL of this remote will be used to access the repository. The refspec of this remote will be used by default when you do not provide a refspec on the command line. The entry in the config file would appear like this:
[remote "<name>"]
url = <URL>
pushurl = <pushurl>
push = <refspec>
fetch = <refspec>The <pushurl> is used for pushes only. It is optional and defaults to <URL>. Pushing to a remote affects all defined pushurls or all defined urls if no pushurls are defined. Fetch, however, will only fetch from the first defined url if multiple urls are defined.
You can choose to provide the name of a file in $GIT_DIR/remotes. The URL in this file will be used to access the repository. The refspec in this file will be used as default when you do not provide a refspec on the command line. This file should have the following format:
URL: one of the above URL formats
Push: <refspec>
Pull: <refspec>Push: lines are used by git push and Pull: lines are used by git pull and git fetch. Multiple Push: and Pull: lines may be specified for additional branch mappings.
You can choose to provide the name of a file in $GIT_DIR/branches. The URL in this file will be used to access the repository. This file should have the following format:
<URL>#<head>
<URL> is required; #<head> is optional.
Depending on the operation, git will use one of the following refspecs, if you don't provide one on the command line. <branch> is the name of this file in $GIT_DIR/branches and <head> defaults to master.
git fetch uses:
refs/heads/<head>:refs/heads/<branch>
git push uses:
HEAD:refs/heads/<head>
The merge mechanism (git merge and git pull commands) allows the backend merge strategies to be chosen with -s option. Some strategies can also take their own options, which can be passed by giving -X<option> arguments to git merge and/or git pull.
This is the default merge strategy when pulling or merging one branch. This strategy can only resolve two heads using a 3-way merge algorithm. When there is more than one common ancestor that can be used for 3-way merge, it creates a merged tree of the common ancestors and uses that as the reference tree for the 3-way merge. This has been reported to result in fewer merge conflicts without causing mismerges by tests done on actual merge commits taken from Linux 2.6 kernel development history. Additionally this strategy can detect and handle merges involving renames. It does not make use of detected copies. The name for this algorithm is an acronym ("Ostensibly Recursive's Twin") and came from the fact that it was written as a replacement for the previous default algorithm, recursive.
In the case where the path is a submodule, if the submodule commit used on one side of the merge is a descendant of the submodule commit used on the other side of the merge, Git attempts to fast-forward to the descendant. Otherwise, Git will treat this case as a conflict, suggesting as a resolution a submodule commit that is descendant of the conflicting ones, if one exists.
The ort strategy can take the following options:
This option forces conflicting hunks to be auto-resolved cleanly by favoring our version. Changes from the other tree that do not conflict with our side are reflected in the merge result. For a binary file, the entire contents are taken from our side.
This should not be confused with the ours merge strategy, which does not even look at what the other tree contains at all. It discards everything the other tree did, declaring our history contains all that happened in it.
Treats lines with the indicated type of whitespace change as unchanged for the sake of a three-way merge. Whitespace changes mixed with other changes to a line are not ignored. See also the section called “git-diff(1)” -b, -w, --ignore-space-at-eol, and --ignore-cr-at-eol.
With the strategies that use 3-way merge (including the default, ort), if a change is made on both branches, but later reverted on one of the branches, that change will be present in the merged result; some people find this behavior confusing. It occurs because only the heads and the merge base are considered when performing a merge, not the individual commits. The merge algorithm therefore considers the reverted change as no change at all, and substitutes the changed version instead.
Often people use git pull without giving any parameter. Traditionally, this has been equivalent to saying git pull origin. However, when configuration branch.<name>.remote is present while on branch <name>, that value is used instead of origin.
In order to determine what URL to use to fetch from, the value of the configuration remote.<origin>.url is consulted and if there is not any such variable, the value on the URL: line in $GIT_DIR/remotes/<origin> is used.
In order to determine what remote branches to fetch (and optionally store in the remote-tracking branches) when the command is run without any refspec parameters on the command line, values of the configuration variable remote.<origin>.fetch are consulted, and if there aren't any, $GIT_DIR/remotes/<origin> is consulted and its Pull: lines are used. In addition to the refspec formats described in the OPTIONS section, you can have a globbing refspec that looks like this:
refs/heads/*:refs/remotes/origin/*
A globbing refspec must have a non-empty RHS (i.e. must store what were fetched in remote-tracking branches), and its LHS and RHS must end with /*. The above specifies that all remote branches are tracked using remote-tracking branches in refs/remotes/origin/ hierarchy under the same name.
The rule to determine which remote branch to merge after fetching is a bit involved, in order not to break backward compatibility.
If explicit refspecs were given on the command line of git pull, they are all merged.
When no refspec was given on the command line, then git pull uses the refspec from the configuration or $GIT_DIR/remotes/<origin>. In such cases, the following rules apply:
Update the remote-tracking branches for the repository you cloned from, then merge one of them into your current branch:
$ git pull $ git pull origin
Normally the branch merged in is the HEAD of the remote repository, but the choice is determined by the branch.<name>.remote and branch.<name>.merge options; see the section called “git-config(1)” for details.
Merge into the current branch the remote branch next:
$ git pull origin next
This leaves a copy of next temporarily in FETCH_HEAD, and updates the remote-tracking branch origin/next. The same can be done by invoking fetch and merge:
$ git fetch origin $ git merge origin/next
If you tried a pull which resulted in complex conflicts and would want to start over, you can recover with git reset.
The fetch and push protocols are not designed to prevent one side from stealing data from the other repository that was not intended to be shared. If you have private data that you need to protect from a malicious peer, your best option is to store it in another repository. This applies to both clients and servers. In particular, namespaces on a server are not effective for read access control; you should only grant read access to a namespace to clients that you would trust with read access to the entire repository.
The known attack vectors are as follows:
Using --recurse-submodules can only fetch new commits in already checked out submodules right now. When e.g. upstream added a new submodule in the just fetched commits of the superproject the submodule itself cannot be fetched, making it impossible to check out that submodule later without having to do a fetch again. This is expected to be fixed in a future Git version.
the section called “git-fetch(1)”, the section called “git-merge(1)”, the section called “git-config(1)”
Part of the the section called “git(1)” suite
git push [--all | --branches | --mirror | --tags] [--follow-tags] [--atomic] [-n | --dry-run] [--receive-pack=<git-receive-pack>]
[--repo=<repository>] [-f | --force] [-d | --delete] [--prune] [-q | --quiet] [-v | --verbose]
[-u | --set-upstream] [-o <string> | --push-option=<string>]
[--[no-]signed|--signed=(true|false|if-asked)]
[--force-with-lease[=<refname>[:<expect>]] [--force-if-includes]]
[--no-verify] [<repository> [<refspec>…]]
Updates remote refs using local refs, while sending objects necessary to complete the given refs.
You can make interesting things happen to a repository every time you push into it, by setting up hooks there. See documentation for the section called “git-receive-pack(1)”.
When the command line does not specify where to push with the <repository> argument, branch.*.remote configuration for the current branch is consulted to determine where to push. If the configuration is missing, it defaults to origin.
When the command line does not specify what to push with <refspec>... arguments or --all, --mirror, --tags options, the command finds the default <refspec> by consulting remote.*.push configuration, and if it is not found, honors push.default configuration to decide what to push (See the section called “git-config(1)” for the meaning of push.default).
When neither the command-line nor the configuration specifies what to push, the default behavior is used, which corresponds to the simple value for push.default: the current branch is pushed to the corresponding upstream branch, but as a safety measure, the push is aborted if the upstream branch does not have the same name as the local one.
Specify what destination ref to update with what source object. The format of a <refspec> parameter is an optional plus +, followed by the source object <src>, followed by a colon :, followed by the destination ref <dst>.
The <src> is often the name of the branch you would want to push, but it can be any arbitrary "SHA-1 expression", such as master~4 or HEAD (see the section called “gitrevisions(7)”).
The <dst> tells which ref on the remote side is updated with this push. Arbitrary expressions cannot be used here, an actual ref must be named. If git push [<repository>] without any <refspec> argument is set to update some ref at the destination with <src> with remote.<repository>.push configuration variable, :<dst> part can be omitted--such a push will update a ref that <src> normally updates without any <refspec> on the command line. Otherwise, missing :<dst> means to update the same ref as the <src>.
If <dst> doesn't start with refs/ (e.g. refs/heads/master) we will try to infer where in refs/* on the destination <repository> it belongs based on the type of <src> being pushed and whether <dst> is ambiguous.
The object referenced by <src> is used to update the <dst> reference on the remote side. Whether this is allowed depends on where in refs/* the <dst> reference lives as described in detail below, in those sections "update" means any modifications except deletes, which as noted after the next few sections are treated differently.
The refs/heads/* namespace will only accept commit objects, and updates only if they can be fast-forwarded.
The refs/tags/* namespace will accept any kind of object (as commits, trees and blobs can be tagged), and any updates to them will be rejected.
It's possible to push any type of object to any namespace outside of refs/{tags,heads}/*. In the case of tags and commits, these will be treated as if they were the commits inside refs/heads/* for the purposes of whether the update is allowed.
I.e. a fast-forward of commits and tags outside refs/{tags,heads}/* is allowed, even in cases where what's being fast-forwarded is not a commit, but a tag object which happens to point to a new commit which is a fast-forward of the commit the last tag (or commit) it's replacing. Replacing a tag with an entirely different tag is also allowed, if it points to the same commit, as well as pushing a peeled tag, i.e. pushing the commit that existing tag object points to, or a new tag object which an existing commit points to.
Tree and blob objects outside of refs/{tags,heads}/* will be treated the same way as if they were inside refs/tags/*, any update of them will be rejected.
All of the rules described above about what's not allowed as an update can be overridden by adding an the optional leading + to a refspec (or using --force command line option). The only exception to this is that no amount of forcing will make the refs/heads/* namespace accept a non-commit object. Hooks and configuration can also override or amend these rules, see e.g. receive.denyNonFastForwards in the section called “git-config(1)” and pre-receive and update in the section called “githooks(5)”.
Pushing an empty <src> allows you to delete the <dst> ref from the remote repository. Deletions are always accepted without a leading + in the refspec (or --force), except when forbidden by configuration or hooks. See receive.denyDeletes in the section called “git-config(1)” and pre-receive and update in the section called “githooks(5)”.
The special refspec : (or +: to allow non-fast-forward updates) directs Git to push "matching" branches: for every branch that exists on the local side, the remote side is updated if a branch of the same name already exists on the remote side.
tag <tag> means the same as refs/tags/<tag>:refs/tags/<tag>.
Usually, "git push" refuses to update a remote ref that is not an ancestor of the local ref used to overwrite it.
This option overrides this restriction if the current value of the remote ref is the expected value. "git push" fails otherwise.
Imagine that you have to rebase what you have already published. You will have to bypass the "must fast-forward" rule in order to replace the history you originally published with the rebased history. If somebody else built on top of your original history while you are rebasing, the tip of the branch at the remote may advance with their commit, and blindly pushing with --force will lose their work.
This option allows you to say that you expect the history you are updating is what you rebased and want to replace. If the remote ref still points at the commit you specified, you can be sure that no other people did anything to the ref. It is like taking a "lease" on the ref without explicitly locking it, and the remote ref is updated only if the "lease" is still valid.
--force-with-lease alone, without specifying the details, will protect all remote refs that are going to be updated by requiring their current value to be the same as the remote-tracking branch we have for them.
--force-with-lease=<refname>, without specifying the expected value, will protect the named ref (alone), if it is going to be updated, by requiring its current value to be the same as the remote-tracking branch we have for it.
--force-with-lease=<refname>:<expect> will protect the named ref (alone), if it is going to be updated, by requiring its current value to be the same as the specified value <expect> (which is allowed to be different from the remote-tracking branch we have for the refname, or we do not even have to have such a remote-tracking branch when this form is used). If <expect> is the empty string, then the named ref must not already exist.
Note that all forms other than --force-with-lease=<refname>:<expect> that specifies the expected current value of the ref explicitly are still experimental and their semantics may change as we gain experience with this feature.
"--no-force-with-lease" will cancel all the previous --force-with-lease on the command line.
A general note on safety: supplying this option without an expected value, i.e. as --force-with-lease or --force-with-lease=<refname> interacts very badly with anything that implicitly runs git fetch on the remote to be pushed to in the background, e.g. git fetch origin on your repository in a cronjob.
The protection it offers over --force is ensuring that subsequent changes your work wasn't based on aren't clobbered, but this is trivially defeated if some background process is updating refs in the background. We don't have anything except the remote tracking info to go by as a heuristic for refs you're expected to have seen & are willing to clobber.
If your editor or some other system is running git fetch in the background for you a way to mitigate this is to simply set up another remote:
git remote add origin-push $(git config remote.origin.url) git fetch origin-push
Now when the background process runs git fetch origin the references on origin-push won't be updated, and thus commands like:
git push --force-with-lease origin-push
Will fail unless you manually run git fetch origin-push. This method is of course entirely defeated by something that runs git fetch --all, in that case you'd need to either disable it or do something more tedious like:
git fetch # update 'master' from remote git tag base master # mark our base point git rebase -i master # rewrite some commits git push --force-with-lease=master:base master:master
I.e. create a base tag for versions of the upstream code that you've seen and are willing to overwrite, then rewrite history, and finally force push changes to master if the remote version is still at base, regardless of what your local remotes/origin/master has been updated to in the background.
Alternatively, specifying --force-if-includes as an ancillary option along with --force-with-lease[=<refname>] (i.e., without saying what exact commit the ref on the remote side must be pointing at, or which refs on the remote side are being protected) at the time of "push" will verify if updates from the remote-tracking refs that may have been implicitly updated in the background are integrated locally before allowing a forced update.
Usually, the command refuses to update a remote ref that is not an ancestor of the local ref used to overwrite it. Also, when --force-with-lease option is used, the command refuses to update a remote ref whose current value does not match what is expected.
This flag disables these checks, and can cause the remote repository to lose commits; use it with care.
Note that --force applies to all the refs that are pushed, hence using it with push.default set to matching or with multiple push destinations configured with remote.*.push may overwrite refs other than the current branch (including local refs that are strictly behind their remote counterpart). To force a push to only one branch, use a + in front of the refspec to push (e.g git push origin +master to force a push to the master branch). See the <refspec>... section above for details.
Force an update only if the tip of the remote-tracking ref has been integrated locally.
This option enables a check that verifies if the tip of the remote-tracking ref is reachable from one of the "reflog" entries of the local branch based in it for a rewrite. The check ensures that any updates from the remote have been incorporated locally by rejecting the forced update if that is not the case.
If the option is passed without specifying --force-with-lease, or specified along with --force-with-lease=<refname>:<expect>, it is a "no-op".
Specifying --no-force-if-includes disables this behavior.
May be used to make sure all submodule commits used by the revisions to be pushed are available on a remote-tracking branch. If check is used Git will verify that all submodule commits that changed in the revisions to be pushed are available on at least one remote of the submodule. If any commits are missing the push will be aborted and exit with non-zero status. If on-demand is used all submodules that changed in the revisions to be pushed will be pushed. If on-demand was not able to push all necessary revisions it will also be aborted and exit with non-zero status. If only is used all submodules will be pushed while the superproject is left unpushed. A value of no or using --no-recurse-submodules can be used to override the push.recurseSubmodules configuration variable when no submodule recursion is required.
When using on-demand or only, if a submodule has a "push.recurseSubmodules={on-demand,only}" or "submodule.recurse" configuration, further recursion will occur. In this case, "only" is treated as "on-demand".
In general, URLs contain information about the transport protocol, the address of the remote server, and the path to the repository. Depending on the transport protocol, some of this information may be absent.
Git supports ssh, git, http, and https protocols (in addition, ftp and ftps can be used for fetching, but this is inefficient and deprecated; do not use them).
The native transport (i.e. git:// URL) does no authentication and should be used with caution on unsecured networks.
The following syntaxes may be used with them:
An alternative scp-like syntax may also be used with the ssh protocol:
This syntax is only recognized if there are no slashes before the first colon. This helps differentiate a local path that contains a colon. For example the local path foo:bar could be specified as an absolute path or ./foo:bar to avoid being misinterpreted as an ssh url.
The ssh and git protocols additionally support ~<username> expansion:
For local repositories, also supported by Git natively, the following syntaxes may be used:
These two syntaxes are mostly equivalent, except when cloning, when the former implies --local option. See the section called “git-clone(1)” for details.
git clone, git fetch and git pull, but not git push, will also accept a suitable bundle file. See the section called “git-bundle(1)”.
When Git doesn't know how to handle a certain transport protocol, it attempts to use the remote-<transport> remote helper, if one exists. To explicitly request a remote helper, the following syntax may be used:
where <address> may be a path, a server and path, or an arbitrary URL-like string recognized by the specific remote helper being invoked. See the section called “gitremote-helpers(7)” for details.
If there are a large number of similarly-named remote repositories and you want to use a different format for them (such that the URLs you use will be rewritten into URLs that work), you can create a configuration section of the form:
[url "<actual-url-base>"]
insteadOf = <other-url-base>
For example, with this:
[url "git://git.host.xz/"]
insteadOf = host.xz:/path/to/
insteadOf = work:a URL like "work:repo.git" or like "host.xz:/path/to/repo.git" will be rewritten in any context that takes a URL to be "git://git.host.xz/repo.git".
If you want to rewrite URLs for push only, you can create a configuration section of the form:
[url "<actual-url-base>"]
pushInsteadOf = <other-url-base>
For example, with this:
[url "ssh://example.org/"]
pushInsteadOf = git://example.org/a URL like "git://example.org/path/to/repo.git" will be rewritten to "ssh://example.org/path/to/repo.git" for pushes, but pulls will still use the original URL.
The name of one of the following can be used instead of a URL as <repository> argument:
All of these also allow you to omit the refspec from the command line because they each contain a refspec which git will use by default.
You can choose to provide the name of a remote which you had previously configured using the section called “git-remote(1)”, the section called “git-config(1)” or even by a manual edit to the $GIT_DIR/config file. The URL of this remote will be used to access the repository. The refspec of this remote will be used by default when you do not provide a refspec on the command line. The entry in the config file would appear like this:
[remote "<name>"]
url = <URL>
pushurl = <pushurl>
push = <refspec>
fetch = <refspec>The <pushurl> is used for pushes only. It is optional and defaults to <URL>. Pushing to a remote affects all defined pushurls or all defined urls if no pushurls are defined. Fetch, however, will only fetch from the first defined url if multiple urls are defined.
You can choose to provide the name of a file in $GIT_DIR/remotes. The URL in this file will be used to access the repository. The refspec in this file will be used as default when you do not provide a refspec on the command line. This file should have the following format:
URL: one of the above URL formats
Push: <refspec>
Pull: <refspec>Push: lines are used by git push and Pull: lines are used by git pull and git fetch. Multiple Push: and Pull: lines may be specified for additional branch mappings.
You can choose to provide the name of a file in $GIT_DIR/branches. The URL in this file will be used to access the repository. This file should have the following format:
<URL>#<head>
<URL> is required; #<head> is optional.
Depending on the operation, git will use one of the following refspecs, if you don't provide one on the command line. <branch> is the name of this file in $GIT_DIR/branches and <head> defaults to master.
git fetch uses:
refs/heads/<head>:refs/heads/<branch>
git push uses:
HEAD:refs/heads/<head>
The output of "git push" depends on the transport method used; this section describes the output when pushing over the Git protocol (either locally or via ssh).
The status of the push is output in tabular form, with each line representing the status of a single ref. Each line is of the form:
<flag> <summary> <from> -> <to> (<reason>)
If --porcelain is used, then each line of the output is of the form:
<flag> \t <from>:<to> \t <summary> (<reason>)
The status of up-to-date refs is shown only if --porcelain or --verbose option is used.
A single character indicating the status of the ref:
For a successfully pushed ref, the summary shows the old and new values of the ref in a form suitable for using as an argument to git log (this is <old>..<new> in most cases, and <old>...<new> for forced non-fast-forward updates).
For a failed update, more details are given:
When an update changes a branch (or more in general, a ref) that used to point at commit A to point at another commit B, it is called a fast-forward update if and only if B is a descendant of A.
In a fast-forward update from A to B, the set of commits that the original commit A built on top of is a subset of the commits the new commit B builds on top of. Hence, it does not lose any history.
In contrast, a non-fast-forward update will lose history. For example, suppose you and somebody else started at the same commit X, and you built a history leading to commit B while the other person built a history leading to commit A. The history looks like this:
B
/
---X---AFurther suppose that the other person already pushed changes leading to A back to the original repository from which you two obtained the original commit X.
The push done by the other person updated the branch that used to point at commit X to point at commit A. It is a fast-forward.
But if you try to push, you will attempt to update the branch (that now points at A) with commit B. This does not fast-forward. If you did so, the changes introduced by commit A will be lost, because everybody will now start building on top of B.
The command by default does not allow an update that is not a fast-forward to prevent such loss of history.
If you do not want to lose your work (history from X to B) or the work by the other person (history from X to A), you would need to first fetch the history from the repository, create a history that contains changes done by both parties, and push the result back.
You can perform "git pull", resolve potential conflicts, and "git push" the result. A "git pull" will create a merge commit C between commits A and B.
B---C
/ /
---X---AUpdating A with the resulting merge commit will fast-forward and your push will be accepted.
Alternatively, you can rebase your change between X and B on top of A, with "git pull --rebase", and push the result back. The rebase will create a new commit D that builds the change between X and B on top of A.
B D
/ /
---X---AAgain, updating A with this commit will fast-forward and your push will be accepted.
There is another common situation where you may encounter non-fast-forward rejection when you try to push, and it is possible even when you are pushing into a repository nobody else pushes into. After you push commit A yourself (in the first picture in this section), replace it with "git commit --amend" to produce commit B, and you try to push it out, because forgot that you have pushed A out already. In such a case, and only if you are certain that nobody in the meantime fetched your earlier commit A (and started building on top of it), you can run "git push --force" to overwrite it. In other words, "git push --force" is a method reserved for a case where you do mean to lose history.
Without additional configuration, pushes the current branch to the configured upstream (branch.<name>.merge configuration variable) if it has the same name as the current branch, and errors out without pushing otherwise.
The default behavior of this command when no <refspec> is given can be configured by setting the push option of the remote, or the push.default configuration variable.
For example, to default to pushing only the current branch to origin use git config remote.origin.push HEAD. Any valid <refspec> (like the ones in the examples below) can be configured as the default for git push origin.
Use the source ref that matches master (e.g. refs/heads/master) to update the ref that matches satellite/master (most probably refs/remotes/satellite/master) in the mothership repository; do the same for dev and satellite/dev.
See the section describing <refspec>... above for a discussion of the matching semantics.
This is to emulate git fetch run on the mothership using git push that is run in the opposite direction in order to integrate the work done on satellite, and is often necessary when you can only make connection in one way (i.e. satellite can ssh into mothership but mothership cannot initiate connection to satellite because the latter is behind a firewall or does not run sshd).
After running this git push on the satellite machine, you would ssh into the mothership and run git merge there to complete the emulation of git pull that were run on mothership to pull changes made on satellite.
Update the origin repository's master branch with the dev branch, allowing non-fast-forward updates. This can leave unreferenced commits dangling in the origin repository. Consider the following situation, where a fast-forward is not possible:
o---o---o---A---B origin/master
\
X---Y---Z devThe above command would change the origin repository to
A---B (unnamed branch)
/
o---o---o---X---Y---Z masterCommits A and B would no longer belong to a branch with a symbolic name, and so would be unreachable. As such, these commits would be removed by a git gc command on the origin repository.
The fetch and push protocols are not designed to prevent one side from stealing data from the other repository that was not intended to be shared. If you have private data that you need to protect from a malicious peer, your best option is to store it in another repository. This applies to both clients and servers. In particular, namespaces on a server are not effective for read access control; you should only grant read access to a namespace to clients that you would trust with read access to the entire repository.
The known attack vectors are as follows:
Everything below this line in this section is selectively included from the the section called “git-config(1)” documentation. The content is the same as what's found there:
Defines the action git push should take if no refspec is given (whether from the command-line, config, or elsewhere). Different values are well-suited for specific workflows; for instance, in a purely central workflow (i.e. the fetch source is equal to the push destination), upstream is probably what you want. Possible values are:
simple - push the current branch with the same name on the remote.
If you are working on a centralized workflow (pushing to the same repository you pull from, which is typically origin), then you need to configure an upstream branch with the same name.
This mode is the default since Git 2.0, and is the safest option suited for beginners.
matching - push all branches having the same name on both ends. This makes the repository you are pushing to remember the set of branches that will be pushed out (e.g. if you always push maint and master there and no other branches, the repository you push to will have these two branches, and your local maint and master will be pushed there).
To use this mode effectively, you have to make sure all the branches you would push out are ready to be pushed out before running git push, as the whole point of this mode is to allow you to push all of the branches in one go. If you usually finish work on only one branch and push out the result, while other branches are unfinished, this mode is not for you. Also this mode is not suitable for pushing into a shared central repository, as other people may add new branches there, or update the tip of existing branches outside your control.
This used to be the default, but not since Git 2.0 (simple is the new default).
When no --push-option=<option> argument is given from the command line, git push behaves as if each <value> of this variable is given as --push-option=<value>.
This is a multi-valued variable, and an empty value can be used in a higher priority configuration file (e.g. .git/config in a repository) to clear the values inherited from a lower priority configuration files (e.g. $HOME/.gitconfig).
Example: /etc/gitconfig push.pushoption = a push.pushoption = b ~/.gitconfig push.pushoption = c repo/.git/config push.pushoption = push.pushoption = b This will result in only b (a and c are cleared).
Part of the the section called “git(1)” suite
git quiltimport [--dry-run | -n] [--author <author>] [--patches <dir>]
[--series <file>] [--keep-non-patch]
Applies a quilt patchset onto the current Git branch, preserving the patch boundaries, patch order, and patch descriptions present in the quilt patchset.
For each patch the code attempts to extract the author from the patch description. If that fails it falls back to the author specified with --author. If the --author flag was not given the patch description is displayed and the user is asked to interactively enter the author of the patch.
If a subject is not found in the patch description the patch name is preserved as the 1 line subject in the Git description.
The directory to find the quilt patches.
The default for the patch directory is patches or the value of the $QUILT_PATCHES environment variable.
The quilt series file.
The default for the series file is <patches>/series or the value of the $QUILT_SERIES environment variable.
Part of the the section called “git(1)” suite
git range-diff [--color=[<when>]] [--no-color] [<diff-options>]
[--no-dual-color] [--creation-factor=<factor>]
[--left-only | --right-only] [--diff-merges=<format>]
[--remerge-diff]
( <range1> <range2> | <rev1>…<rev2> | <base> <rev1> <rev2> )
[[--] <path>…]
This command shows the differences between two versions of a patch series, or more generally, two commit ranges (ignoring merge commits).
In the presence of <path> arguments, these commit ranges are limited accordingly.
To that end, it first finds pairs of commits from both commit ranges that correspond with each other. Two commits are said to correspond when the diff between their patches (i.e. the author information, the commit message and the commit diff) is reasonably small compared to the patches' size. See ``Algorithm`` below for details.
Finally, the list of matching commits is shown in the order of the second commit range, with unmatched commits being inserted just after all of their ancestors have been shown.
There are three ways to specify the commit ranges:
When the commit diffs differ, git range-diff` recreates the original diffs coloring, and adds outer -/+ diff markers with the background being red/green to make it easier to see e.g. when there was a change in what exact lines were added.
Additionally, the commit diff lines that are only present in the first commit range are shown "dimmed" (this can be overridden using the color.diff.<slot> config setting where <slot> is one of contextDimmed, oldDimmed and newDimmed), and the commit diff lines that are only present in the second commit range are shown in bold (which can be overridden using the config settings color.diff.<slot> with <slot> being one of contextBold, oldBold or newBold).
This is known to range-diff as "dual coloring". Use --no-dual-color to revert to color all lines according to the outer diff markers (and completely ignore the inner diff when it comes to color).
Instead of ignoring merge commits, generate diffs for them using the corresponding --diff-merges=<format> option of the section called “git-log(1)”, and include them in the comparison.
Note: In the common case, the remerge mode will be the most natural one to use, as it shows only the diff on top of what Git's merge machinery would have produced. In other words, if a merge commit is the result of a non-conflicting git merge, the remerge mode will represent it with an empty diff.
git range-diff also accepts the regular diff options (see the section called “git-diff(1)”), most notably the --color=[<when>] and --no-color options. These options are used when generating the "diff between patches", i.e. to compare the author, commit message and diff of corresponding old/new commits. There is currently no means to tweak most of the diff options passed to git log when generating those patches.
The output of the range-diff command is subject to change. It is intended to be human-readable porcelain output, not something that can be used across versions of Git to get a textually stable range-diff (as opposed to something like the --stable option to the section called “git-patch-id(1)”). There's also no equivalent of the section called “git-apply(1)” for range-diff, the output is not intended to be machine-readable.
This is particularly true when passing in diff options. Currently some options like --stat can, as an emergent effect, produce output that's quite useless in the context of range-diff. Future versions of range-diff may learn to interpret such options in a manner specific to range-diff (e.g. for --stat producing human-readable output which summarizes how the diffstat changed).
This command uses the diff.color.* and pager.range-diff settings (the latter is on by default). See the section called “git-config(1)”.
When a rebase required merge conflicts to be resolved, compare the changes introduced by the rebase directly afterwards using:
$ git range-diff @{u} @{1} @A typical output of git range-diff would look like this:
-: ------- > 1: 0ddba11 Prepare for the inevitable!
1: c0debee = 2: cab005e Add a helpful message at the start
2: f00dbal ! 3: decafe1 Describe a bug
@@ -1,3 +1,3 @@
Author: A U Thor <author@example.com>
-TODO: Describe a bug
+Describe a bug
@@ -324,5 +324,6
This is expected.
-+What is unexpected is that it will also crash.
++Unexpectedly, it also crashes. This is a bug, and the jury is
++still out there how to fix it best. See ticket #314 for details.
Contact
3: bedead < -: ------- TO-UNDOIn this example, there are 3 old and 3 new commits, where the developer removed the 3rd, added a new one before the first two, and modified the commit message of the 2nd commit as well as its diff.
When the output goes to a terminal, it is color-coded by default, just like regular git diff's output. In addition, the first line (adding a commit) is green, the last line (deleting a commit) is red, the second line (with a perfect match) is yellow like the commit header of git show's output, and the third line colors the old commit red, the new one green and the rest like git show's commit header.
A naive color-coded diff of diffs is actually a bit hard to read, though, as it colors the entire lines red or green. The line that added "What is unexpected" in the old commit, for example, is completely red, even if the intent of the old commit was to add something.
To help with that, range uses the --dual-color mode by default. In this mode, the diff of diffs will retain the original diff colors, and prefix the lines with -/+ markers that have their background red or green, to make it more obvious that they describe how the diff itself changed.
The general idea is this: we generate a cost matrix between the commits in both commit ranges, then solve the least-cost assignment.
The cost matrix is populated thusly: for each pair of commits, both diffs are generated and the "diff of diffs" is generated, with 3 context lines, then the number of lines in that diff is used as cost.
To avoid false positives (e.g. when a patch has been removed, and an unrelated patch has been added between two iterations of the same patch series), the cost matrix is extended to allow for that, by adding fixed-cost entries for wholesale deletes/adds.
Example: Let commits 1--2 be the first iteration of a patch series and A--C the second iteration. Let's assume that A is a cherry-pick of 2, and C is a cherry-pick of 1 but with a small modification (say, a fixed typo). Visualize the commits as a bipartite graph:
1 A
2 B
CWe are looking for a "best" explanation of the new series in terms of the old one. We can represent an "explanation" as an edge in the graph:
1 A
/
2 --------' B
CThis explanation comes for "free" because there was no change. Similarly C could be explained using 1, but that comes at some cost c>0 because of the modification:
1 ----. A
| /
2 ----+---' B
|
`----- C
c>0In mathematical terms, what we are looking for is some sort of a minimum cost bipartite matching; 1` is matched to C at some cost, etc. The underlying graph is in fact a complete bipartite graph; the cost we associate with every edge is the size of the diff between the two commits patches. To explain also new commits, we introduce dummy nodes on both sides:
1 ----. A
| /
2 ----+---' B
|
o `----- C
c>0
o o
o oThe cost of an edge o--C is the size of C's diff, modified by a fudge factor that should be smaller than 100%. The cost of an edge o--o is free. The fudge factor is necessary because even if 1 and C have nothing in common, they may still share a few empty lines and such, possibly making the assignment 1--C, o--o slightly cheaper than 1--o, o--C even if 1 and C have nothing in common. With the fudge factor we require a much larger common part to consider patches as corresponding.
The overall time needed to compute this algorithm is the time needed to compute n+m commit diffs and then n*m diffs of patches, plus the time needed to compute the least-cost assignment between n and m diffs. Git uses an implementation of the Jonker-Volgenant algorithm to solve the assignment problem, which has cubic runtime complexity. The matching found in this case will look like this:
1 ----. A
| /
2 ----+---' B
.--+-----'
o -' `----- C
c>0
o ---------- o
o ---------- oPart of the the section called “git(1)” suite
git read-tree [(-m [--trivial] [--aggressive] | --reset | --prefix=<prefix>)
[-u | -i]] [--index-output=<file>] [--no-sparse-checkout]
(--empty | <tree-ish1> [<tree-ish2> [<tree-ish3>]])
Reads the tree information given by <tree-ish> into the index, but does not actually update any of the files it "caches". (see: the section called “git-checkout-index(1)”)
Optionally, it can merge a tree into the index, perform a fast-forward (i.e. 2-way) merge, or a 3-way merge, with the -m flag. When used with -m, the -u flag causes it to also update the files in the work tree with the result of the merge.
Only trivial merges are done by git read-tree itself. Only conflicting paths will be in an unmerged state when git read-tree returns.
Usually a three-way merge by git read-tree resolves the merge for really trivial cases and leaves other cases unresolved in the index, so that porcelains can implement different merge policies. This flag makes the command resolve a few more cases internally:
If -m is specified, git read-tree can perform 3 kinds of merge, a single tree merge if only 1 tree is given, a fast-forward merge with 2 trees, or a 3-way merge if 3 or more trees are provided.
If only 1 tree is specified, git read-tree operates as if the user did not specify -m, except that if the original index has an entry for a given pathname, and the contents of the path match with the tree being read, the stat info from the index is used. (In other words, the index's stat()s take precedence over the merged tree's).
That means that if you do a git read-tree -m <newtree> followed by a git checkout-index -f -u -a, the git checkout-index only checks out the stuff that really changed.
This is used to avoid unnecessary false hits when git diff-files is run after git read-tree.
Typically, this is invoked as git read-tree -m $H $M, where $H is the head commit of the current repository, and $M is the head of a foreign tree, which is simply ahead of $H (i.e. we are in a fast-forward situation).
When two trees are specified, the user is telling git read-tree the following:
In this case, the git read-tree -m $H $M command makes sure that no local change is lost as the result of this "merge". Here are the "carry forward" rules, where "I" denotes the index, "clean" means that index and work tree coincide, and "exists"/"nothing" refer to the presence of a path in the specified commit:
I H M Result
-------------------------------------------------------
0 nothing nothing nothing (does not happen)
1 nothing nothing exists use M
2 nothing exists nothing remove path from index
3 nothing exists exists, use M if "initial checkout",
H == M keep index otherwise
exists, fail
H != M
clean I==H I==M
------------------
4 yes N/A N/A nothing nothing keep index
5 no N/A N/A nothing nothing keep index
6 yes N/A yes nothing exists keep index
7 no N/A yes nothing exists keep index
8 yes N/A no nothing exists fail
9 no N/A no nothing exists fail
10 yes yes N/A exists nothing remove path from index
11 no yes N/A exists nothing fail
12 yes no N/A exists nothing fail
13 no no N/A exists nothing fail
clean (H==M)
------
14 yes exists exists keep index
15 no exists exists keep index
clean I==H I==M (H!=M)
------------------
16 yes no no exists exists fail
17 no no no exists exists fail
18 yes no yes exists exists keep index
19 no no yes exists exists keep index
20 yes yes no exists exists use M
21 no yes no exists exists failIn all "keep index" cases, the index entry stays as in the original index file. If the entry is not up to date, git read-tree keeps the copy in the work tree intact when operating under the -u flag.
When this form of git read-tree returns successfully, you can see which of the "local changes" that you made were carried forward by running git diff-index --cached $M. Note that this does not necessarily match what git diff-index --cached $H would have produced before such a two tree merge. This is because of cases 18 and 19 -- if you already had the changes in $M (e.g. maybe you picked it up via e-mail in a patch form), git diff-index --cached $H would have told you about the change before this merge, but it would not show in git diff-index --cached $M output after the two-tree merge.
Case 3 is slightly tricky and needs explanation. The result from this rule logically should be to remove the path if the user staged the removal of the path and then switching to a new branch. That however will prevent the initial checkout from happening, so the rule is modified to use M (new tree) only when the content of the index is empty. Otherwise the removal of the path is kept as long as $H and $M are the same.
Each "index" entry has two bits worth of "stage" state. stage 0 is the normal one, and is the only one you'd see in any kind of normal use.
However, when you do git read-tree with three trees, the "stage" starts out at 1.
This means that you can do
$ git read-tree -m <tree1> <tree2> <tree3>
and you will end up with an index with all of the <tree1> entries in "stage1", all of the <tree2> entries in "stage2" and all of the <tree3> entries in "stage3". When performing a merge of another branch into the current branch, we use the common ancestor tree as <tree1>, the current branch head as <tree2>, and the other branch head as <tree3>.
Furthermore, git read-tree has special-case logic that says: if you see a file that matches in all respects in the following states, it "collapses" back to "stage0":
The git write-tree command refuses to write a nonsensical tree, and it will complain about unmerged entries if it sees a single entry that is not stage 0.
OK, this all sounds like a collection of totally nonsensical rules, but it's actually exactly what you want in order to do a fast merge. The different stages represent the "result tree" (stage 0, aka "merged"), the original tree (stage 1, aka "orig"), and the two trees you are trying to merge (stage 2 and 3 respectively).
The order of stages 1, 2 and 3 (hence the order of three <tree-ish> command-line arguments) are significant when you start a 3-way merge with an index file that is already populated. Here is an outline of how the algorithm works:
the index file saves and restores with all this information, so you can merge things incrementally, but as long as it has entries in stages 1/2/3 (i.e., "unmerged entries") you can't write the result. So now the merge algorithm ends up being really simple:
You would normally use git merge-index with supplied git merge-one-file to do this last step. The script updates the files in the working tree as it merges each path and at the end of a successful merge.
When you start a 3-way merge with an index file that is already populated, it is assumed that it represents the state of the files in your work tree, and you can even have files with changes unrecorded in the index file. It is further assumed that this state is "derived" from the stage 2 tree. The 3-way merge refuses to run if it finds an entry in the original index file that does not match stage 2.
This is done to prevent you from losing your work-in-progress changes, and mixing your random changes in an unrelated merge commit. To illustrate, suppose you start from what has been committed last to your repository:
$ JC=`git rev-parse --verify "HEAD^0"` $ git checkout-index -f -u -a $JC
You do random edits, without running git update-index. And then you notice that the tip of your "upstream" tree has advanced since you pulled from him:
$ git fetch git://.... linus $ LT=`git rev-parse FETCH_HEAD`
Your work tree is still based on your HEAD ($JC), but you have some edits since. Three-way merge makes sure that you have not added or modified index entries since $JC, and if you haven't, then does the right thing. So with the following sequence:
$ git read-tree -m -u `git merge-base $JC $LT` $JC $LT $ git merge-index git-merge-one-file -a $ echo "Merge with Linus" | \ git commit-tree `git write-tree` -p $JC -p $LT
what you would commit is a pure merge between $JC and $LT without your work-in-progress changes, and your work tree would be updated to the result of the merge.
However, if you have local changes in the working tree that would be overwritten by this merge, git read-tree will refuse to run to prevent your changes from being lost.
In other words, there is no need to worry about what exists only in the working tree. When you have local changes in a part of the project that is not involved in the merge, your changes do not interfere with the merge, and are kept intact. When they do interfere, the merge does not even start (git read-tree complains loudly and fails without modifying anything). In such a case, you can simply continue doing what you were in the middle of doing, and when your working tree is ready (i.e. you have finished your work-in-progress), attempt the merge again.
Note: The skip-worktree capabilities in the section called “git-update-index(1)” and read-tree predated the introduction of the section called “git-sparse-checkout(1)”. Users are encouraged to use the sparse-checkout command in preference to these plumbing commands for sparse-checkout/skip-worktree related needs. However, the information below might be useful to users trying to understand the pattern style used in non-cone mode of the sparse-checkout command.
"Sparse checkout" allows populating the working directory sparsely. It uses the skip-worktree bit (see the section called “git-update-index(1)”) to tell Git whether a file in the working directory is worth looking at.
git read-tree and other merge-based commands (git merge, git checkout…) can help maintaining the skip-worktree bitmap and working directory update. $GIT_DIR/info/sparse-checkout is used to define the skip-worktree reference bitmap. When git read-tree needs to update the working directory, it resets the skip-worktree bit in the index based on this file, which uses the same syntax as .gitignore files. If an entry matches a pattern in this file, or the entry corresponds to a file present in the working tree, then skip-worktree will not be set on that entry. Otherwise, skip-worktree will be set.
Then it compares the new skip-worktree value with the previous one. If skip-worktree turns from set to unset, it will add the corresponding file back. If it turns from unset to set, that file will be removed.
While $GIT_DIR/info/sparse-checkout is usually used to specify what files are in, you can also specify what files are not in, using negate patterns. For example, to remove the file unwanted:
/* !unwanted
Another tricky thing is fully repopulating the working directory when you no longer want sparse checkout. You cannot just disable "sparse checkout" because skip-worktree bits are still in the index and your working directory is still sparsely populated. You should re-populate the working directory with the $GIT_DIR/info/sparse-checkout file content as follows:
/*
Then you can disable sparse checkout. Sparse checkout support in git read-tree and similar commands is disabled by default. You need to turn core.sparseCheckout on in order to have sparse checkout support.
the section called “git-write-tree(1)”, the section called “git-ls-files(1)”, the section called “gitignore(5)”, the section called “git-sparse-checkout(1)”
Part of the the section called “git(1)” suite
git rebase [-i | --interactive] [<options>] [--exec <cmd>]
[--onto <newbase> | --keep-base] [<upstream> [<branch>]]
git rebase [-i | --interactive] [<options>] [--exec <cmd>] [--onto <newbase>]
--root [<branch>]
git rebase (--continue|--skip|--abort|--quit|--edit-todo|--show-current-patch)
If <branch> is specified, git rebase will perform an automatic git switch <branch> before doing anything else. Otherwise it remains on the current branch.
If <upstream> is not specified, the upstream configured in branch.<name>.remote and branch.<name>.merge options will be used (see the section called “git-config(1)” for details) and the --fork-point option is assumed. If you are currently not on any branch or if the current branch does not have a configured upstream, the rebase will abort.
All changes made by commits in the current branch but that are not in <upstream> are saved to a temporary area. This is the same set of commits that would be shown by git log <upstream>..HEAD; or by git log 'fork_point'..HEAD, if --fork-point is active (see the description on --fork-point below); or by git log HEAD, if the --root option is specified.
The current branch is reset to <upstream> or <newbase> if the --onto option was supplied. This has the exact same effect as git reset --hard <upstream> (or <newbase>). ORIG_HEAD is set to point at the tip of the branch before the reset.
ORIG_HEAD is not guaranteed to still point to the previous branch tip at the end of the rebase if other commands that write that pseudo-ref (e.g. git reset) are used during the rebase. The previous branch tip, however, is accessible using the reflog of the current branch (i.e. @{1}, see the section called “gitrevisions(7)”).
The commits that were previously saved into the temporary area are then reapplied to the current branch, one by one, in order. Note that any commits in HEAD which introduce the same textual changes as a commit in HEAD..<upstream> are omitted (i.e., a patch already accepted upstream with a different commit message or timestamp will be skipped).
It is possible that a merge failure will prevent this process from being completely automatic. You will have to resolve any such merge failure and run git rebase --continue. Another option is to bypass the commit that caused the merge failure with git rebase --skip. To check out the original <branch> and remove the .git/rebase-apply working files, use the command git rebase --abort instead.
Assume the following history exists and the current branch is "topic":
A---B---C topic
/
D---E---F---G masterFrom this point, the result of either of the following commands:
git rebase master git rebase master topic
would be:
A'--B'--C' topic
/
D---E---F---G masterNOTE: The latter form is just a short-hand of git checkout topic followed by git rebase master. When rebase exits topic will remain the checked-out branch.
If the upstream branch already contains a change you have made (e.g., because you mailed a patch which was applied upstream), then that commit will be skipped and warnings will be issued (if the merge backend is used). For example, running git rebase master on the following history (in which A' and A introduce the same set of changes, but have different committer information):
A---B---C topic
/
D---E---A'---F masterwill result in:
B'---C' topic
/
D---E---A'---F masterHere is how you would transplant a topic branch based on one branch to another, to pretend that you forked the topic branch from the latter branch, using rebase --onto.
First let's assume your topic is based on branch next. For example, a feature developed in topic depends on some functionality which is found in next.
o---o---o---o---o master
\
o---o---o---o---o next
\
o---o---o topicWe want to make topic forked from branch master; for example, because the functionality on which topic depends was merged into the more stable master branch. We want our tree to look like this:
o---o---o---o---o master
| \
| o'--o'--o' topic
\
o---o---o---o---o nextWe can get this using the following command:
git rebase --onto master next topic
Another example of --onto option is to rebase part of a branch. If we have the following situation:
H---I---J topicB
/
E---F---G topicA
/
A---B---C---D masterthen the command
git rebase --onto master topicA topicB
would result in:
H'--I'--J' topicB
/
| E---F---G topicA
|/
A---B---C---D masterThis is useful when topicB does not depend on topicA.
A range of commits could also be removed with rebase. If we have the following situation:
E---F---G---H---I---J topicA
then the command
git rebase --onto topicA~5 topicA~3 topicA
would result in the removal of commits F and G:
E---H'---I'---J' topicA
This is useful if F and G were flawed in some way, or should not be part of topicA. Note that the argument to --onto and the <upstream> parameter can be any valid commit-ish.
In case of conflict, git rebase will stop at the first problematic commit and leave conflict markers in the tree. You can use git diff to locate the markers (<<<<<<) and make edits to resolve the conflict. For each file you edit, you need to tell Git that the conflict has been resolved, typically this would be done with
git add <filename>
After resolving the conflict manually and updating the index with the desired resolution, you can continue the rebasing process with
git rebase --continue
Alternatively, you can undo the git rebase with
git rebase --abort
The options in this section cannot be used with any other option, including not with each other:
Starting point at which to create the new commits. If the --onto option is not specified, the starting point is <upstream>. May be any valid commit, and not just an existing branch name.
As a special case, you may use "A...B" as a shortcut for the merge base of A and B if there is exactly one merge base. You can leave out at most one of A and B, in which case it defaults to HEAD.
Set the starting point at which to create the new commits to the merge base of <upstream> and <branch>. Running git rebase --keep-base <upstream> <branch> is equivalent to running git rebase --reapply-cherry-picks --no-fork-point --onto <upstream>...<branch> <upstream> <branch>.
This option is useful in the case where one is developing a feature on top of an upstream branch. While the feature is being worked on, the upstream branch may advance and it may not be the best idea to keep rebasing on top of the upstream but to keep the base commit as-is. As the base commit is unchanged this option implies --reapply-cherry-picks to avoid losing commits.
Although both this option and --fork-point find the merge base between <upstream> and <branch>, this option uses the merge base as the starting point on which new commits will be created, whereas --fork-point uses the merge base to determine the set of commits which will be rebased.
See also INCOMPATIBLE OPTIONS below.
Use applying strategies to rebase (calling git-am internally). This option may become a no-op in the future once the merge backend handles everything the apply one does.
See also INCOMPATIBLE OPTIONS below.
How to handle commits that are not empty to start and are not clean cherry-picks of any upstream commit, but which become empty after rebasing (because they contain a subset of already upstream changes):
Note that commits which start empty are kept (unless --no-keep-empty is specified), and commits which are clean cherry-picks (as determined by git log --cherry-mark ...) are detected and dropped as a preliminary step (unless --reapply-cherry-picks or --keep-base is passed).
See also INCOMPATIBLE OPTIONS below.
Do not keep commits that start empty before the rebase (i.e. that do not change anything from its parent) in the result. The default is to keep commits which start empty, since creating such commits requires passing the --allow-empty override flag to git commit, signifying that a user is very intentionally creating such a commit and thus wants to keep it.
Usage of this flag will probably be rare, since you can get rid of commits that start empty by just firing up an interactive rebase and removing the lines corresponding to the commits you don't want. This flag exists as a convenient shortcut, such as for cases where external tools generate many empty commits and you want them all removed.
For commits which do not start empty but become empty after rebasing, see the --empty flag.
See also INCOMPATIBLE OPTIONS below.
Reapply all clean cherry-picks of any upstream commit instead of preemptively dropping them. (If these commits then become empty after rebasing, because they contain a subset of already upstream changes, the behavior towards them is controlled by the --empty flag.)
In the absence of --keep-base (or if --no-reapply-cherry-picks is given), these commits will be automatically dropped. Because this necessitates reading all upstream commits, this can be expensive in repositories with a large number of upstream commits that need to be read. When using the merge backend, warnings will be issued for each dropped commit (unless --quiet is given). Advice will also be issued unless advice.skippedCherryPicks is set to false (see the section called “git-config(1)”).
--reapply-cherry-picks allows rebase to forgo reading all upstream commits, potentially improving performance.
See also INCOMPATIBLE OPTIONS below.
No-op. Rebasing commits with an empty message used to fail and this option would override that behavior, allowing commits with empty messages to be rebased. Now commits with an empty message do not cause rebasing to halt.
See also INCOMPATIBLE OPTIONS below.
Using merging strategies to rebase (default).
Note that a rebase merge works by replaying each commit from the working branch on top of the <upstream> branch. Because of this, when a merge conflict happens, the side reported as ours is the so-far rebased series, starting with <upstream>, and theirs is the working branch. In other words, the sides are swapped.
See also INCOMPATIBLE OPTIONS below.
Use the given merge strategy, instead of the default ort. This implies --merge.
Because git rebase replays each commit from the working branch on top of the <upstream> branch using the given strategy, using the ours strategy simply empties all patches from the <branch>, which makes little sense.
See also INCOMPATIBLE OPTIONS below.
Pass the <strategy-option> through to the merge strategy. This implies --merge and, if no strategy has been specified, -s ort. Note the reversal of ours and theirs as noted above for the -m option.
See also INCOMPATIBLE OPTIONS below.
Ensure at least <n> lines of surrounding context match before and after each change. When fewer lines of surrounding context exist they all must match. By default no context is ever ignored. Implies --apply.
See also INCOMPATIBLE OPTIONS below.
Individually replay all rebased commits instead of fast-forwarding over the unchanged ones. This ensures that the entire history of the rebased branch is composed of new commits.
You may find this helpful after reverting a topic branch merge, as this option recreates the topic branch with fresh commits so it can be remerged successfully without needing to "revert the reversion" (see the revert-a-faulty-merge How-To for details).
Use reflog to find a better common ancestor between <upstream> and <branch> when calculating which commits have been introduced by <branch>.
When --fork-point is active, fork_point will be used instead of <upstream> to calculate the set of commits to rebase, where fork_point is the result of git merge-base --fork-point <upstream> <branch> command (see the section called “git-merge-base(1)”). If fork_point ends up being empty, the <upstream> will be used as a fallback.
If <upstream> or --keep-base is given on the command line, then the default is --no-fork-point, otherwise the default is --fork-point. See also rebase.forkpoint in the section called “git-config(1)”.
If your branch was based on <upstream> but <upstream> was rewound and your branch contains commits which were dropped, this option can be used with --keep-base in order to drop those commits from your branch.
See also INCOMPATIBLE OPTIONS below.
Ignore whitespace differences when trying to reconcile differences. Currently, each backend implements an approximation of this behavior:
This flag is passed to the git apply program (see the section called “git-apply(1)”) that applies the patch. Implies --apply.
See also INCOMPATIBLE OPTIONS below.
Instead of using the author date of the original commit, use the current time as the author date of the rebased commit. This option implies --force-rebase.
See also INCOMPATIBLE OPTIONS below.
Add a Signed-off-by trailer to all the rebased commits. Note that if --interactive is given then only commits marked to be picked, edited or reworded will have the trailer added.
See also INCOMPATIBLE OPTIONS below.
Make a list of the commits which are about to be rebased. Let the user edit that list before rebasing. This mode can also be used to split commits (see SPLITTING COMMITS below).
The commit list format can be changed by setting the configuration option rebase.instructionFormat. A customized instruction format will automatically have the commit hash prepended to the format.
See also INCOMPATIBLE OPTIONS below.
By default, a rebase will simply drop merge commits from the todo list, and put the rebased commits into a single, linear branch. With --rebase-merges, the rebase will instead try to preserve the branching structure within the commits that are to be rebased, by recreating the merge commits. Any resolved merge conflicts or manual amendments in these merge commits will have to be resolved/re-applied manually. --no-rebase-merges can be used to countermand both the rebase.rebaseMerges config option and a previous --rebase-merges.
When rebasing merges, there are two modes: rebase-cousins and no-rebase-cousins. If the mode is not specified, it defaults to no-rebase-cousins. In no-rebase-cousins mode, commits which do not have <upstream> as direct ancestor will keep their original branch point, i.e. commits that would be excluded by the section called “git-log(1)”'s --ancestry-path option will keep their original ancestry by default. In rebase-cousins mode, such commits are instead rebased onto <upstream> (or <onto>, if specified).
It is currently only possible to recreate the merge commits using the ort merge strategy; different merge strategies can be used only via explicit exec git merge -s <strategy> [...] commands.
See also REBASING MERGES and INCOMPATIBLE OPTIONS below.
Append "exec <cmd>" after each line creating a commit in the final history. <cmd> will be interpreted as one or more shell commands. Any command that fails will interrupt the rebase, with exit code 1.
You may execute several commands by either using one instance of --exec with several commands:
git rebase -i --exec "cmd1 && cmd2 && ..."
or by giving more than one --exec:
git rebase -i --exec "cmd1" --exec "cmd2" --exec ...
If --autosquash is used, exec lines will not be appended for the intermediate commits, and will only appear at the end of each squash/fixup series.
This uses the --interactive machinery internally, but it can be run without an explicit --interactive.
See also INCOMPATIBLE OPTIONS below.
Rebase all commits reachable from <branch>, instead of limiting them with an <upstream>. This allows you to rebase the root commit(s) on a branch.
See also INCOMPATIBLE OPTIONS below.
Automatically squash commits with specially formatted messages into previous commits being rebased. If a commit message starts with "squash! ", "fixup! " or "amend! ", the remainder of the title is taken as a commit specifier, which matches a previous commit if it matches the title or the hash of that commit. If no commit matches fully, matches of the specifier with the start of commit titles are considered.
In the rebase todo list, the actions of squash, fixup and amend commits are changed from pick to squash, fixup or fixup -C, respectively, and they are moved right after the commit they modify. The --interactive option can be used to review and edit the todo list before proceeding.
The recommended way to create commits with squash markers is by using the --squash, --fixup, --fixup=amend: or --fixup=reword: options of the section called “git-commit(1)”, which take the target commit as an argument and automatically fill in the title of the new commit from that.
Setting configuration variable rebase.autoSquash to true enables auto-squashing by default for interactive rebase. The --no-autosquash option can be used to override that setting.
See also INCOMPATIBLE OPTIONS below.
Automatically reschedule exec commands that failed. This only makes sense in interactive mode (or when an --exec option was provided).
This option applies once a rebase is started. It is preserved for the whole rebase based on, in order, the command line option provided to the initial git rebase, the rebase.rescheduleFailedExec configuration (see the section called “git-config(1)” or "CONFIGURATION" below), or it defaults to false.
Recording this option for the whole rebase is a convenience feature. Otherwise an explicit --no-reschedule-failed-exec at the start would be overridden by the presence of a rebase.rescheduleFailedExec=true configuration when git rebase --continue is invoked. Currently, you cannot pass --[no-]reschedule-failed-exec to git rebase --continue.
Automatically force-update any branches that point to commits that are being rebased. Any branches that are checked out in a worktree are not updated in this way.
If the configuration variable rebase.updateRefs is set, then this option can be used to override and disable this setting.
See also INCOMPATIBLE OPTIONS below.
The following options:
are incompatible with the following options:
In addition, the following pairs of options are incompatible:
git rebase has two primary backends: apply and merge. (The apply backend used to be known as the am backend, but the name led to confusion as it looks like a verb instead of a noun. Also, the merge backend used to be known as the interactive backend, but it is now used for non-interactive cases as well. Both were renamed based on lower-level functionality that underpinned each.) There are some subtle differences in how these two backends behave:
The apply backend unfortunately drops intentionally empty commits, i.e. commits that started empty, though these are rare in practice. It also drops commits that become empty and has no option for controlling this behavior.
The merge backend keeps intentionally empty commits by default (though with -i they are marked as empty in the todo list editor, or they can be dropped automatically with --no-keep-empty).
Similar to the apply backend, by default the merge backend drops commits that become empty unless -i/--interactive is specified (in which case it stops and asks the user what to do). The merge backend also has an --empty=(drop|keep|stop) option for changing the behavior of handling commits that become empty.
Due to the lack of accurate tree information (arising from constructing fake ancestors with the limited information available in patches), directory rename detection is disabled in the apply backend. Disabled directory rename detection means that if one side of history renames a directory and the other adds new files to the old directory, then the new files will be left behind in the old directory without any warning at the time of rebasing that you may want to move these files into the new directory.
Directory rename detection works with the merge backend to provide you warnings in such cases.
The apply backend works by creating a sequence of patches (by calling format-patch internally), and then applying the patches in sequence (calling am internally). Patches are composed of multiple hunks, each with line numbers, a context region, and the actual changes. The line numbers have to be taken with some offset, since the other side will likely have inserted or deleted lines earlier in the file. The context region is meant to help find how to adjust the line numbers in order to apply the changes to the right lines. However, if multiple areas of the code have the same surrounding lines of context, the wrong one can be picked. There are real-world cases where this has caused commits to be reapplied incorrectly with no conflicts reported. Setting diff.context to a larger value may prevent such types of problems, but increases the chance of spurious conflicts (since it will require more lines of matching context to apply).
The merge backend works with a full copy of each relevant file, insulating it from these types of problems.
When there are content conflicts, the merge machinery tries to annotate each side's conflict markers with the commits where the content came from. Since the apply backend drops the original information about the rebased commits and their parents (and instead generates new fake commits based off limited information in the generated patches), those commits cannot be identified; instead it has to fall back to a commit summary. Also, when merge.conflictStyle is set to diff3 or zdiff3, the apply backend will use "constructed merge base" to label the content from the merge base, and thus provide no information about the merge base commit whatsoever.
The merge backend works with the full commits on both sides of history and thus has no such limitations.
The apply backend has not traditionally called the post-commit hook, while the merge backend has. Both have called the post-checkout hook, though the merge backend has squelched its output. Further, both backends only call the post-checkout hook with the starting point commit of the rebase, not the intermediate commits nor the final commit. In each case, the calling of these hooks was by accident of implementation rather than by design (both backends were originally implemented as shell scripts and happened to invoke other commands like git checkout or git commit that would call the hooks). Both backends should have the same behavior, though it is not entirely clear which, if any, is correct. We will likely make rebase stop calling either of these hooks in the future.
The apply backend has safety problems with an ill-timed interrupt; if the user presses Ctrl-C at the wrong time to try to abort the rebase, the rebase can enter a state where it cannot be aborted with a subsequent git rebase --abort. The merge backend does not appear to suffer from the same shortcoming. (See https://lore.kernel.org/git/20200207132152.GC2868@szeder.dev/ for details.)
When a conflict occurs while rebasing, rebase stops and asks the user to resolve. Since the user may need to make notable changes while resolving conflicts, after conflicts are resolved and the user has run git rebase --continue, the rebase should open an editor and ask the user to update the commit message. The merge backend does this, while the apply backend blindly applies the original commit message.
There are a few more behavioral differences that most folks would probably consider inconsequential but which are mentioned for completeness:
The merge mechanism (git merge and git pull commands) allows the backend merge strategies to be chosen with -s option. Some strategies can also take their own options, which can be passed by giving -X<option> arguments to git merge and/or git pull.
This is the default merge strategy when pulling or merging one branch. This strategy can only resolve two heads using a 3-way merge algorithm. When there is more than one common ancestor that can be used for 3-way merge, it creates a merged tree of the common ancestors and uses that as the reference tree for the 3-way merge. This has been reported to result in fewer merge conflicts without causing mismerges by tests done on actual merge commits taken from Linux 2.6 kernel development history. Additionally this strategy can detect and handle merges involving renames. It does not make use of detected copies. The name for this algorithm is an acronym ("Ostensibly Recursive's Twin") and came from the fact that it was written as a replacement for the previous default algorithm, recursive.
In the case where the path is a submodule, if the submodule commit used on one side of the merge is a descendant of the submodule commit used on the other side of the merge, Git attempts to fast-forward to the descendant. Otherwise, Git will treat this case as a conflict, suggesting as a resolution a submodule commit that is descendant of the conflicting ones, if one exists.
The ort strategy can take the following options:
This option forces conflicting hunks to be auto-resolved cleanly by favoring our version. Changes from the other tree that do not conflict with our side are reflected in the merge result. For a binary file, the entire contents are taken from our side.
This should not be confused with the ours merge strategy, which does not even look at what the other tree contains at all. It discards everything the other tree did, declaring our history contains all that happened in it.
Treats lines with the indicated type of whitespace change as unchanged for the sake of a three-way merge. Whitespace changes mixed with other changes to a line are not ignored. See also the section called “git-diff(1)” -b, -w, --ignore-space-at-eol, and --ignore-cr-at-eol.
With the strategies that use 3-way merge (including the default, ort), if a change is made on both branches, but later reverted on one of the branches, that change will be present in the merged result; some people find this behavior confusing. It occurs because only the heads and the merge base are considered when performing a merge, not the individual commits. The merge algorithm therefore considers the reverted change as no change at all, and substitutes the changed version instead.
You should understand the implications of using git rebase on a repository that you share. See also RECOVERING FROM UPSTREAM REBASE below.
When the rebase is run, it will first execute a pre-rebase hook if one exists. You can use this hook to do sanity checks and reject the rebase if it isn't appropriate. Please see the template pre-rebase hook script for an example.
Upon completion, <branch> will be the current branch.
Rebasing interactively means that you have a chance to edit the commits which are rebased. You can reorder the commits, and you can remove them (weeding out bad or otherwise unwanted patches).
The interactive mode is meant for this type of workflow:
where point 2. consists of several instances of
a) regular use
b) independent fixup
Sometimes the thing fixed in b.2. cannot be amended to the not-quite perfect commit it fixes, because that commit is buried deeply in a patch series. That is exactly what interactive rebase is for: use it after plenty of "a"s and "b"s, by rearranging and editing commits, and squashing multiple commits into one.
Start it with the last commit you want to retain as-is:
git rebase -i <after-this-commit>
An editor will be fired up with all the commits in your current branch (ignoring merge commits), which come after the given commit. You can reorder the commits in this list to your heart's content, and you can remove them. The list looks more or less like this:
pick deadbee The oneline of this commit pick fa1afe1 The oneline of the next commit ...
The oneline descriptions are purely for your pleasure; git rebase will not look at them but at the commit names ("deadbee" and "fa1afe1" in this example), so do not delete or edit the names.
By replacing the command "pick" with the command "edit", you can tell git rebase to stop after applying that commit, so that you can edit the files and/or the commit message, amend the commit, and continue rebasing.
To interrupt the rebase (just like an "edit" command would do, but without cherry-picking any commit first), use the "break" command.
If you just want to edit the commit message for a commit, replace the command "pick" with the command "reword".
To drop a commit, replace the command "pick" with "drop", or just delete the matching line.
If you want to fold two or more commits into one, replace the command "pick" for the second and subsequent commits with "squash" or "fixup". If the commits had different authors, the folded commit will be attributed to the author of the first commit. The suggested commit message for the folded commit is the concatenation of the first commit's message with those identified by "squash" commands, omitting the messages of commits identified by "fixup" commands, unless "fixup -c" is used. In that case the suggested commit message is only the message of the "fixup -c" commit, and an editor is opened allowing you to edit the message. The contents (patch) of the "fixup -c" commit are still incorporated into the folded commit. If there is more than one "fixup -c" commit, the message from the final one is used. You can also use "fixup -C" to get the same behavior as "fixup -c" except without opening an editor.
git rebase will stop when "pick" has been replaced with "edit" or when a command fails due to merge errors. When you are done editing and/or resolving conflicts you can continue with git rebase --continue.
For example, if you want to reorder the last 5 commits, such that what was HEAD~4 becomes the new HEAD. To achieve that, you would call git rebase like this:
$ git rebase -i HEAD~5
And move the first patch to the end of the list.
You might want to recreate merge commits, e.g. if you have a history like this:
X
\
A---M---B
/
---o---O---P---QSuppose you want to rebase the side branch starting at "A" to "Q". Make sure that the current HEAD is "B", and call
$ git rebase -i -r --onto Q O
Reordering and editing commits usually creates untested intermediate steps. You may want to check that your history editing did not break anything by running a test, or at least recompiling at intermediate points in history by using the "exec" command (shortcut "x"). You may do so by creating a todo list like this one:
pick deadbee Implement feature XXX fixup f1a5c00 Fix to feature XXX exec make pick c0ffeee The oneline of the next commit edit deadbab The oneline of the commit after exec cd subdir; make test ...
The interactive rebase will stop when a command fails (i.e. exits with non-0 status) to give you an opportunity to fix the problem. You can continue with git rebase --continue.
The "exec" command launches the command in a shell (the default one, usually /bin/sh), so you can use shell features (like "cd", ">", ";" …). The command is run from the root of the working tree.
$ git rebase -i --exec "make test"
This command lets you check that intermediate commits are compilable. The todo list becomes like that:
pick 5928aea one exec make test pick 04d0fda two exec make test pick ba46169 three exec make test pick f4593f9 four exec make test
In interactive mode, you can mark commits with the action "edit". However, this does not necessarily mean that git rebase expects the result of this edit to be exactly one commit. Indeed, you can undo the commit, or you can add other commits. This can be used to split a commit into two:
If you are not absolutely sure that the intermediate revisions are consistent (they compile, pass the testsuite, etc.) you should use git stash to stash away the not-yet-committed changes after each commit, test, and amend the commit if fixes are necessary.
Rebasing (or any other form of rewriting) a branch that others have based work on is a bad idea: anyone downstream of it is forced to manually fix their history. This section explains how to do the fix from the downstream's point of view. The real fix, however, would be to avoid rebasing the upstream in the first place.
To illustrate, suppose you are in a situation where someone develops a subsystem branch, and you are working on a topic that is dependent on this subsystem. You might end up with a history like the following:
o---o---o---o---o---o---o---o master
\
o---o---o---o---o subsystem
\
*---*---* topicIf subsystem is rebased against master, the following happens:
o---o---o---o---o---o---o---o master
\ \
o---o---o---o---o o'--o'--o'--o'--o' subsystem
\
*---*---* topicIf you now continue development as usual, and eventually merge topic to subsystem, the commits from subsystem will remain duplicated forever:
o---o---o---o---o---o---o---o master
\ \
o---o---o---o---o o'--o'--o'--o'--o'--M subsystem
\ /
*---*---*-..........-*--* topicSuch duplicates are generally frowned upon because they clutter up history, making it harder to follow. To clean things up, you need to transplant the commits on topic to the new subsystem tip, i.e., rebase topic. This becomes a ripple effect: anyone downstream from topic is forced to rebase too, and so on!
There are two kinds of fixes, discussed in the following subsections:
Only works if the changes (patch IDs based on the diff contents) on subsystem are literally the same before and after the rebase subsystem did.
In that case, the fix is easy because git rebase knows to skip changes that are already present in the new upstream (unless --reapply-cherry-picks is given). So if you say (assuming you're on topic)
$ git rebase subsystem
you will end up with the fixed history
o---o---o---o---o---o---o---o master
\
o'--o'--o'--o'--o' subsystem
\
*---*---* topicThings get more complicated if the subsystem changes do not exactly correspond to the ones before the rebase.
While an "easy case recovery" sometimes appears to be successful even in the hard case, it may have unintended consequences. For example, a commit that was removed via git rebase --interactive will be resurrected!
The idea is to manually tell git rebase "where the old subsystem ended and your topic began", that is, what the old merge base between them was. You will have to find a way to name the last commit of the old subsystem, for example:
You can then transplant the old subsystem..topic to the new tip by saying (for the reflog case, and assuming you are on topic already):
$ git rebase --onto subsystem subsystem@{1}The ripple effect of a "hard case" recovery is especially bad: everyone downstream from topic will now have to perform a "hard case" recovery too!
The interactive rebase command was originally designed to handle individual patch series. As such, it makes sense to exclude merge commits from the todo list, as the developer may have merged the then-current master while working on the branch, only to rebase all the commits onto master eventually (skipping the merge commits).
However, there are legitimate reasons why a developer may want to recreate merge commits: to keep the branch structure (or "commit topology") when working on multiple, inter-related branches.
In the following example, the developer works on a topic branch that refactors the way buttons are defined, and on another topic branch that uses that refactoring to implement a "Report a bug" button. The output of git log --graph --format=%s -5 may look like this:
* Merge branch 'report-a-bug' |\ | * Add the feedback button * | Merge branch 'refactor-button' |\ \ | |/ | * Use the Button class for all buttons | * Extract a generic Button class from the DownloadButton one
The developer might want to rebase those commits to a newer master while keeping the branch topology, for example when the first topic branch is expected to be integrated into master much earlier than the second one, say, to resolve merge conflicts with changes to the DownloadButton class that made it into master.
This rebase can be performed using the --rebase-merges option. It will generate a todo list looking like this:
label onto # Branch: refactor-button reset onto pick 123456 Extract a generic Button class from the DownloadButton one pick 654321 Use the Button class for all buttons label refactor-button # Branch: report-a-bug reset refactor-button # Use the Button class for all buttons pick abcdef Add the feedback button label report-a-bug reset onto merge -C a1b2c3 refactor-button # Merge 'refactor-button' merge -C 6f5e4d report-a-bug # Merge 'report-a-bug'
In contrast to a regular interactive rebase, there are label, reset and merge commands in addition to pick ones.
The label command associates a label with the current HEAD when that command is executed. These labels are created as worktree-local refs (refs/rewritten/<label>) that will be deleted when the rebase finishes. That way, rebase operations in multiple worktrees linked to the same repository do not interfere with one another. If the label command fails, it is rescheduled immediately, with a helpful message how to proceed.
The reset command resets the HEAD, index and worktree to the specified revision. It is similar to an exec git reset --hard <label>, but refuses to overwrite untracked files. If the reset command fails, it is rescheduled immediately, with a helpful message how to edit the todo list (this typically happens when a reset command was inserted into the todo list manually and contains a typo).
The merge command will merge the specified revision(s) into whatever is HEAD at that time. With -C <original-commit>, the commit message of the specified merge commit will be used. When the -C is changed to a lower-case -c, the message will be opened in an editor after a successful merge so that the user can edit the message.
If a merge command fails for any reason other than merge conflicts (i.e. when the merge operation did not even start), it is rescheduled immediately.
By default, the merge command will use the ort merge strategy for regular merges, and octopus for octopus merges. One can specify a default strategy for all merges using the --strategy argument when invoking rebase, or can override specific merges in the interactive list of commands by using an exec command to call git merge explicitly with a --strategy argument. Note that when calling git merge explicitly like this, you can make use of the fact that the labels are worktree-local refs (the ref refs/rewritten/onto would correspond to the label onto, for example) in order to refer to the branches you want to merge.
Note: the first command (label onto) labels the revision onto which the commits are rebased; The name onto is just a convention, as a nod to the --onto option.
It is also possible to introduce completely new merge commits from scratch by adding a command of the form merge <merge-head>. This form will generate a tentative commit message and always open an editor to let the user edit it. This can be useful e.g. when a topic branch turns out to address more than a single concern and wants to be split into two or even more topic branches. Consider this todo list:
pick 192837 Switch from GNU Makefiles to CMake pick 5a6c7e Document the switch to CMake pick 918273 Fix detection of OpenSSL in CMake pick afbecd http: add support for TLS v1.3 pick fdbaec Fix detection of cURL in CMake on Windows
The one commit in this list that is not related to CMake may very well have been motivated by working on fixing all those bugs introduced by switching to CMake, but it addresses a different concern. To split this branch into two topic branches, the todo list could be edited like this:
label onto pick afbecd http: add support for TLS v1.3 label tlsv1.3 reset onto pick 192837 Switch from GNU Makefiles to CMake pick 918273 Fix detection of OpenSSL in CMake pick fdbaec Fix detection of cURL in CMake on Windows pick 5a6c7e Document the switch to CMake label cmake reset onto merge tlsv1.3 merge cmake
Everything below this line in this section is selectively included from the the section called “git-config(1)” documentation. The content is the same as what's found there:
If set to true, git rebase will use abbreviated command names in the todo list resulting in something like this:
p deadbee The oneline of the commit
p fa1afe1 The oneline of the next commit
...instead of:
pick deadbee The oneline of the commit
pick fa1afe1 The oneline of the next commit
...Defaults to false.
Part of the the section called “git(1)” suite
Invoked by git send-pack and updates the repository with the information fed from the remote end.
This command is usually not invoked directly by the end user. The UI for the protocol is on the git send-pack side, and the program pair is meant to be used to push updates to a remote repository. For pull operations, see the section called “git-fetch-pack(1)”.
The command allows for the creation and fast-forwarding of sha1 refs (heads/tags) on the remote end (strictly speaking, it is the local end git-receive-pack runs, but to the user who is sitting at the send-pack end, it is updating the remote. Confused?)
There are other real-world examples of using update and post-update hooks found in the Documentation/howto directory.
git-receive-pack honours the receive.denyNonFastForwards config option, which tells it if updates to a ref should be denied if they are not fast-forwards.
A number of other receive.* config options are available to tweak its behavior, see the section called “git-config(1)”.
Before any ref is updated, if $GIT_DIR/hooks/pre-receive file exists and is executable, it will be invoked once with no parameters. The standard input of the hook will be one line per ref to be updated:
sha1-old SP sha1-new SP refname LF
The refname value is relative to $GIT_DIR; e.g. for the master head this is "refs/heads/master". The two sha1 values before each refname are the object names for the refname before and after the update. Refs to be created will have sha1-old equal to 0{40}, while refs to be deleted will have sha1-new equal to 0{40}, otherwise sha1-old and sha1-new should be valid objects in the repository.
When accepting a signed push (see the section called “git-push(1)”), the signed push certificate is stored in a blob and an environment variable GIT_PUSH_CERT can be consulted for its object name. See the description of post-receive hook for an example. In addition, the certificate is verified using GPG and the result is exported with the following environment variables:
This hook is called before any refname is updated and before any fast-forward checks are performed.
If the pre-receive hook exits with a non-zero exit status no updates will be performed, and the update, post-receive and post-update hooks will not be invoked either. This can be useful to quickly bail out if the update is not to be supported.
See the notes on the quarantine environment below.
Before each ref is updated, if $GIT_DIR/hooks/update file exists and is executable, it is invoked once per ref, with three parameters:
$GIT_DIR/hooks/update refname sha1-old sha1-new
The refname parameter is relative to $GIT_DIR; e.g. for the master head this is "refs/heads/master". The two sha1 arguments are the object names for the refname before and after the update. Note that the hook is called before the refname is updated, so either sha1-old is 0{40} (meaning there is no such ref yet), or it should match what is recorded in refname.
The hook should exit with non-zero status if it wants to disallow updating the named ref. Otherwise it should exit with zero.
Successful execution (a zero exit status) of this hook does not ensure the ref will actually be updated, it is only a prerequisite. As such it is not a good idea to send notices (e.g. email) from this hook. Consider using the post-receive hook instead.
After all refs were updated (or attempted to be updated), if any ref update was successful, and if $GIT_DIR/hooks/post-receive file exists and is executable, it will be invoked once with no parameters. The standard input of the hook will be one line for each successfully updated ref:
sha1-old SP sha1-new SP refname LF
The refname value is relative to $GIT_DIR; e.g. for the master head this is "refs/heads/master". The two sha1 values before each refname are the object names for the refname before and after the update. Refs that were created will have sha1-old equal to 0{40}, while refs that were deleted will have sha1-new equal to 0{40}, otherwise sha1-old and sha1-new should be valid objects in the repository.
The GIT_PUSH_CERT* environment variables can be inspected, just as in pre-receive hook, after accepting a signed push.
Using this hook, it is easy to generate mails describing the updates to the repository. This example script sends one mail message per ref listing the commits pushed to the repository, and logs the push certificates of signed pushes with good signatures to a logger service:
#!/bin/sh
# mail out commit update information.
while read oval nval ref
do
if expr "$oval" : '0*$' >/dev/null
then
echo "Created a new ref, with the following commits:"
git rev-list --pretty "$nval"
else
echo "New commits:"
git rev-list --pretty "$nval" "^$oval"
fi |
mail -s "Changes to ref $ref" commit-list@mydomain
done
# log signed push certificate, if any
if test -n "${GIT_PUSH_CERT-}" && test ${GIT_PUSH_CERT_STATUS} = G
then
(
echo expected nonce is ${GIT_PUSH_NONCE}
git cat-file blob ${GIT_PUSH_CERT}
) | mail -s "push certificate from $GIT_PUSH_CERT_SIGNER" push-log@mydomain
fi
exit 0The exit code from this hook invocation is ignored, however a non-zero exit code will generate an error message.
Note that it is possible for refname to not have sha1-new when this hook runs. This can easily occur if another user modifies the ref after it was updated by git-receive-pack, but before the hook was able to evaluate it. It is recommended that hooks rely on sha1-new rather than the current value of refname.
After all other processing, if at least one ref was updated, and if $GIT_DIR/hooks/post-update file exists and is executable, then post-update will be called with the list of refs that have been updated. This can be used to implement any repository wide cleanup tasks.
The exit code from this hook invocation is ignored; the only thing left for git-receive-pack to do at that point is to exit itself anyway.
This hook can be used, for example, to run git update-server-info if the repository is packed and is served via a dumb transport.
#!/bin/sh exec git update-server-info
When receive-pack takes in objects, they are placed into a temporary "quarantine" directory within the $GIT_DIR/objects directory and migrated into the main object store only after the pre-receive hook has completed. If the push fails before then, the temporary directory is removed entirely.
This has a few user-visible effects and caveats:
Part of the the section called “git(1)” suite
git reflog [show] [<log-options>] [<ref>]
git reflog list
git reflog expire [--expire=<time>] [--expire-unreachable=<time>]
[--rewrite] [--updateref] [--stale-fix]
[--dry-run | -n] [--verbose] [--all [--single-worktree] | <refs>…]
git reflog delete [--rewrite] [--updateref]
[--dry-run | -n] [--verbose] <ref>@{<specifier>}…
git reflog drop [--all [--single-worktree] | <refs>…]
git reflog exists <ref>
This command manages the information recorded in the reflogs.
Reference logs, or "reflogs", record when the tips of branches and other references were updated in the local repository. Reflogs are useful in various Git commands, to specify the old value of a reference. For example, HEAD@{2} means "where HEAD used to be two moves ago", master@{one.week.ago} means "where master used to point to one week ago in this local repository", and so on. See the section called “gitrevisions(7)” for more details.
The command takes various subcommands, and different options depending on the subcommand:
The "show" subcommand (which is also the default, in the absence of any subcommands) shows the log of the reference provided in the command-line (or HEAD, by default). The reflog covers all recent actions, and in addition the HEAD reflog records branch switching. git reflog show is an alias for git log -g --abbrev-commit --pretty=oneline; see the section called “git-log(1)” for more information.
The "list" subcommand lists all refs which have a corresponding reflog.
The "expire" subcommand prunes older reflog entries. Entries older than expire time, or entries older than expire-unreachable time and not reachable from the current tip, are removed from the reflog. This is typically not used directly by end users -- instead, see the section called “git-gc(1)”.
The "delete" subcommand deletes single entries from the reflog, but not the reflog itself. Its argument must be an exact entry (e.g. "git reflog delete master@{2}"). This subcommand is also typically not used directly by end users.
The "drop" subcommand completely removes the reflog for the specified references. This is in contrast to "expire" and "delete", both of which can be used to delete reflog entries, but not the reflog itself.
The "exists" subcommand checks whether a ref has a reflog. It exits with zero status if the reflog exists, and non-zero status if it does not.
Prune any reflog entries that point to "broken commits". A broken commit is a commit that is not reachable from any of the reference tips and that refers, directly or indirectly, to a missing commit, tree, or blob object.
This computation involves traversing all the reachable objects, i.e. it has the same cost as git prune. It is primarily intended to fix corruption caused by garbage collecting using older versions of Git, which didn't protect objects referred to by reflogs.
git reflog delete accepts options --updateref, --rewrite, -n, --dry-run, and --verbose, with the same meanings as when they are used with expire.
Part of the the section called “git(1)” suite
gitrefsmigrate--ref-format=<format> [--no-reflog] [--dry-run]
gitrefsverify[--strict] [--verbose]
The following options are specific to git refs migrate:
The ref format to migrate the ref store to. Can be one of:
The following options are specific to git refs verify:
The ref format migration has several known limitations in its current form:
These limitations may eventually be lifted.
Part of the the section called “git(1)” suite
This remote helper uses the specified <command> to connect to a remote Git server.
Data written to stdin of the specified <command> is assumed to be sent to a git:// server, git-upload-pack, git-receive-pack or git-upload-archive (depending on situation), and data read from stdout of <command> is assumed to be received from the same service.
Command and arguments are separated by an unescaped space.
The following sequences have a special meaning:
This argument will not be passed to <command>. Instead, it will cause the helper to start by sending git:// service requests to the remote side with the service field set to an appropriate value and the repository field set to the rest of the argument. Default is not to send such a request.
This is useful if the remote side is git:// server accessed over some tunnel.
This remote helper is transparently used by Git when you use commands such as "git fetch <URL>", "git clone <URL>", , "git push <URL>" or "git remote add <nick> <URL>", where <URL> begins with ext::. Examples:
Part of the the section called “git(1)” suite
This helper uses specified file descriptors to connect to a remote Git server. This is not meant for end users but for programs and scripts calling git fetch, push, or archive.
If only <infd> is given, it is assumed to be a bidirectional socket connected to a remote Git server (git-upload-pack, git-receive-pack, or git-upload-archive). If both <infd> and <outfd> are given, they are assumed to be pipes connected to a remote Git server (<infd> being the inbound pipe and <outfd> being the outbound pipe).
It is assumed that any handshaking procedures have already been completed (such as sending service request for git://) before this helper is started.
<anything> can be any string. It is ignored. It is meant for providing information to the user in the URL in case that URL is displayed in some context.
Part of the the section called “git(1)” suite
git remote [-v | --verbose]
git remote add [-t <branch>] [-m <master>] [-f] [--[no-]tags] [--mirror=(fetch|push)] <name> <URL>
git remote rename [--[no-]progress] <old> <new>
git remote remove <name>
git remote set-head <name> (-a | --auto | -d | --delete | <branch>)
git remote set-branches [--add] <name> <branch>…
git remote get-url [--push] [--all] <name>
git remote set-url [--push] <name> <newurl> [<oldurl>]
git remote set-url --add [--push] <name> <newurl>
git remote set-url --delete [--push] <name> <URL>
git remote [-v | --verbose] show [-n] <name>…
git remote prune [-n | --dry-run] <name>…
git remote [-v | --verbose] update [-p | --prune] [(<group> | <remote>)…]
With no arguments, shows a list of existing remotes. Several subcommands are available to perform operations on the remotes.
Add a remote named <name> for the repository at <URL>. The command git fetch <name> can then be used to create and update remote-tracking branches <name>/<branch>.
With -f option, git fetch <name> is run immediately after the remote information is set up.
With --tags option, git fetch <name> imports every tag from the remote repository.
With --no-tags option, git fetch <name> does not import tags from the remote repository.
By default, only tags on fetched branches are imported (see the section called “git-fetch(1)”).
With -t <branch> option, instead of the default glob refspec for the remote to track all branches under the refs/remotes/<name>/ namespace, a refspec to track only <branch> is created. You can give more than one -t <branch> to track multiple branches without grabbing all branches.
With -m <master> option, a symbolic-ref refs/remotes/<name>/HEAD is set up to point at remote's <master> branch. See also the set-head command.
When a fetch mirror is created with --mirror=fetch, the refs will not be stored in the refs/remotes/ namespace, but rather everything in refs/ on the remote will be directly mirrored into refs/ in the local repository. This option only makes sense in bare repositories, because a fetch would overwrite any local commits.
When a push mirror is created with --mirror=push, then git push will always behave as if --mirror was passed.
Rename the remote named <old> to <new>. All remote-tracking branches and configuration settings for the remote are updated.
In case <old> and <new> are the same, and <old> is a file under $GIT_DIR/remotes or $GIT_DIR/branches, the remote is converted to the configuration file format.
Sets or deletes the default branch (i.e. the target of the symbolic-ref refs/remotes/<name>/HEAD) for the named remote. Having a default branch for a remote is not required, but allows the name of the remote to be specified in lieu of a specific branch. For example, if the default branch for origin is set to master, then origin may be specified wherever you would normally specify origin/master.
With -d or --delete, the symbolic ref refs/remotes/<name>/HEAD is deleted.
With -a or --auto, the remote is queried to determine its HEAD, then the symbolic-ref refs/remotes/<name>/HEAD is set to the same branch. e.g., if the remote HEAD is pointed at next, git remote set-head origin -a will set the symbolic-ref refs/remotes/origin/HEAD to refs/remotes/origin/next. This will only work if refs/remotes/origin/next already exists; if not it must be fetched first.
Use <branch> to set the symbolic-ref refs/remotes/<name>/HEAD explicitly. e.g., git remote set-head origin master will set the symbolic-ref refs/remotes/origin/HEAD to refs/remotes/origin/master. This will only work if refs/remotes/origin/master already exists; if not it must be fetched first.
Changes the list of branches tracked by the named remote. This can be used to track a subset of the available remote branches after the initial setup for a remote.
The named branches will be interpreted as if specified with the -t option on the git remote add command line.
With --add, instead of replacing the list of currently tracked branches, adds to that list.
Retrieves the URLs for a remote. Configurations for insteadOf and pushInsteadOf are expanded here. By default, only the first URL is listed.
With --push, push URLs are queried rather than fetch URLs.
With --all, all URLs for the remote will be listed.
Changes URLs for the remote. Sets first URL for remote <name> that matches regex <oldurl> (first URL if no <oldurl> is given) to <newurl>. If <oldurl> doesn't match any URL, an error occurs and nothing is changed.
With --push, push URLs are manipulated instead of fetch URLs.
With --add, instead of changing existing URLs, new URL is added.
With --delete, instead of changing existing URLs, all URLs matching regex <URL> are deleted for remote <name>. Trying to delete all non-push URLs is an error.
Note that the push URL and the fetch URL, even though they can be set differently, must still refer to the same place. What you pushed to the push URL should be what you would see if you immediately fetched from the fetch URL. If you are trying to fetch from one place (e.g. your upstream) and push to another (e.g. your publishing repository), use two separate remotes.
Gives some information about the remote <name>.
With -n option, the remote heads are not queried first with git ls-remote <name>; cached information is used instead.
Deletes stale references associated with <name>. By default, stale remote-tracking branches under <name> are deleted, but depending on global configuration and the configuration of the remote we might even prune local tags that haven't been pushed there. Equivalent to git fetch --prune <name>, except that no new references will be fetched.
See the PRUNING section of the section called “git-fetch(1)” for what it'll prune depending on various configuration.
With --dry-run option, report what branches would be pruned, but do not actually prune them.
Fetch updates for remotes or remote groups in the repository as defined by remotes.<group>. If neither group nor remote is specified on the command line, the configuration parameter remotes.default will be used; if remotes.default is not defined, all remotes which do not have the configuration parameter remote.<name>.skipDefaultUpdate set to true will be updated. (See the section called “git-config(1)”).
With --prune option, run pruning against all the remotes that are updated.
The remote configuration is achieved using the remote.origin.url and remote.origin.fetch configuration variables. (See the section called “git-config(1)”).
On success, the exit status is 0.
When subcommands such as add, rename, and remove can't find the remote in question, the exit status is 2. When the remote already exists, the exit status is 3.
On any other error, the exit status may be any other non-zero value.
Add a new remote, fetch, and check out a branch from it
$ git remote origin $ git branch -r origin/HEAD -> origin/master origin/master $ git remote add staging git://git.kernel.org/.../gregkh/staging.git $ git remote origin staging $ git fetch staging ... From git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging * [new branch] master -> staging/master * [new branch] staging-linus -> staging/staging-linus * [new branch] staging-next -> staging/staging-next $ git branch -r origin/HEAD -> origin/master origin/master staging/master staging/staging-linus staging/staging-next $ git switch -c staging staging/master ...
Imitate git clone but track only selected branches
$ mkdir project.git $ cd project.git $ git init $ git remote add -f -t master -m master origin git://example.com/git.git/ $ git merge origin
the section called “git-fetch(1)” the section called “git-branch(1)” the section called “git-config(1)”
Part of the the section called “git(1)” suite
git repack [-a] [-A] [-d] [-f] [-F] [-l] [-n] [-q] [-b] [-m]
[--window=<n>] [--depth=<n>] [--threads=<n>] [--keep-pack=<pack-name>]
[--write-midx] [--name-hash-version=<n>]
This command is used to combine all objects that do not currently reside in a "pack", into a pack. It can also be used to re-organize existing packs into a single, more efficient pack.
A pack is a collection of objects, individually compressed, with delta compression applied, stored in a single file, with an associated index file.
Packs are used to reduce the load on mirror systems, backup engines, disk storage, etc.
Instead of incrementally packing the unpacked objects, pack everything referenced into a single pack. Especially useful when packing a repository that is used for private development. Use with -d. This will clean up the objects that git prune leaves behind, but git fsck --full --dangling shows as dangling.
Note that users fetching over dumb protocols will have to fetch the whole new pack in order to get any contained object, no matter how many other objects in that pack they already have locally.
Promisor packfiles are repacked separately: if there are packfiles that have an associated ".promisor" file, these packfiles will be repacked into another separate pack, and an empty ".promisor" file corresponding to the new separate pack will be written.
These two options affect how the objects contained in the pack are stored using delta compression. The objects are first internally sorted by type, size and optionally names and compared against the other objects within --window to see if using delta compression saves space. --depth limits the maximum delta depth; making it too deep affects the performance on the unpacker side, because delta data needs to be applied that many times to get to the necessary object.
The default value for --window is 10 and --depth is 50. The maximum depth is 4095.
Arrange resulting pack structure so that each successive pack contains at least <factor> times the number of objects as the next-largest pack.
git repack ensures this by determining a "cut" of packfiles that need to be repacked into one in order to ensure a geometric progression. It picks the smallest set of packfiles such that as many of the larger packfiles (by count of objects contained in that pack) may be left intact.
Unlike other repack modes, the set of objects to pack is determined uniquely by the set of packs being "rolled-up"; in other words, the packs determined to need to be combined in order to restore a geometric progression.
Loose objects are implicitly included in this "roll-up", without respect to their reachability. This is subject to change in the future.
When writing a multi-pack bitmap, git repack selects the largest resulting pack as the preferred pack for object selection by the MIDX (see the section called “git-multi-pack-index(1)”).
Various configuration variables affect packing, see the section called “git-config(1)” (search for "pack" and "delta").
By default, the command passes --delta-base-offset option to git pack-objects; this typically results in slightly smaller packs, but the generated packs are incompatible with versions of Git older than version 1.4.4. If you need to share your repository with such ancient Git versions, either directly or via the dumb http protocol, then you need to set the configuration variable repack.UseDeltaBaseOffset to "false" and repack. Access from old Git versions over the native protocol is unaffected by this option as the conversion is performed on the fly as needed in that case.
Delta compression is not used on objects larger than the core.bigFileThreshold configuration variable and on files with the attribute delta set to false.
Part of the the section called “git(1)” suite
git replace [-f] <object> <replacement>
git replace [-f] --edit <object>
git replace [-f] --graft <commit> [<parent>…]
git replace [-f] --convert-graft-file
git replace -d <object>…
git replace [--format=<format>] [-l [<pattern>]]
Adds a replace reference in refs/replace/ namespace.
The name of the replace reference is the SHA-1 of the object that is replaced. The content of the replace reference is the SHA-1 of the replacement object.
The replaced object and the replacement object must be of the same type. This restriction can be bypassed using -f.
Unless -f is given, the replace reference must not yet exist.
There is no other restriction on the replaced and replacement objects. Merge commits can be replaced by non-merge commits and vice versa.
Replacement references will be used by default by all Git commands except those doing reachability traversal (prune, pack transfer and fsck).
It is possible to disable the use of replacement references for any command using the --no-replace-objects option just after git.
For example if commit foo has been replaced by commit bar:
$ git --no-replace-objects cat-file commit foo
shows information about commit foo, while:
$ git cat-file commit foo
shows information about commit bar.
The GIT_NO_REPLACE_OBJECTS environment variable can be set to achieve the same effect as the --no-replace-objects option.
The following formats are available:
the section called “git-hash-object(1)”, the section called “git-rebase(1)”, and git-filter-repo, among other git commands, can be used to create replacement objects from existing objects. The --edit option can also be used with git replace to create a replacement object by editing an existing object.
If you want to replace many blobs, trees or commits that are part of a string of commits, you may just want to create a replacement string of commits and then only replace the commit at the tip of the target string of commits with the commit at the tip of the replacement string of commits.
Comparing blobs or trees that have been replaced with those that replace them will not work properly. And using git reset --hard to go back to a replaced commit will move the branch to the replacement commit instead of the replaced commit.
There may be other problems when using git rev-list related to pending objects.
the section called “git-hash-object(1)” the section called “git-rebase(1)” the section called “git-tag(1)” the section called “git-branch(1)” the section called “git-commit(1)” the section called “git-var(1)” the section called “git(1)” git-filter-repo
Part of the the section called “git(1)” suite
(EXPERIMENTAL!) git replay ([--contained] --onto <newbase> | --advance <branch>) <revision-range>…
Takes ranges of commits and replays them onto a new location. Leaves the working tree and the index untouched, and updates no references. The output of this command is meant to be used as input to git update-ref --stdin, which would update the relevant branches (see the OUTPUT section below).
THIS COMMAND IS EXPERIMENTAL. THE BEHAVIOR MAY CHANGE.
Starting point at which to create the new commits. May be any valid commit, and not just an existing branch name.
When --onto is specified, the update-ref command(s) in the output will update the branch(es) in the revision range to point at the new commits, similar to the way how git rebase --update-refs updates multiple branches in the affected range.
Starting point at which to create the new commits; must be a branch name.
When --advance is specified, the update-ref command(s) in the output will update the branch passed as an argument to --advance to point at the new commits (in other words, this mimics a cherry-pick operation).
Besides specifying a range of commits that should be listed using the special notations explained in the description, additional commit limiting may be applied.
Using more options generally further limits the output (e.g. --since=<date1> limits to commits newer than <date1>, and using it with --grep=<pattern> further limits to commits whose log message has a line that matches <pattern>), unless otherwise noted.
Note that these are applied before commit ordering and formatting options, such as --reverse.
Limit the commits output to ones with a log message that matches the specified pattern (regular expression). With more than one --grep=<pattern>, commits whose message matches any of the given patterns are chosen (but see --all-match).
When --notes is in effect, the message from the notes is matched as if it were part of the log message.
Consider the limiting patterns to be Perl-compatible regular expressions.
Support for these types of regular expressions is an optional compile-time dependency. If Git wasn't compiled with support for them providing this option will cause it to die.
Show only commits which have at least (or at most) that many parent commits. In particular, --max-parents=1 is the same as --no-merges, --min-parents=2 is the same as --merges. --max-parents=0 gives all root commits and --min-parents=3 all octopus merges.
--no-min-parents and --no-max-parents reset these limits (to no limit) again. Equivalent forms are --min-parents=0 (any commit has 0 or more parents) and --max-parents=-1 (negative numbers denote no upper limit).
Do not include refs matching <glob-pattern> that the next --all, --branches, --tags, --remotes, or --glob would otherwise consider. Repetitions of this option accumulate exclusion patterns up to the next --all, --branches, --tags, --remotes, or --glob option (other options or arguments do not clear accumulated patterns).
The patterns given should not begin with refs/heads, refs/tags, or refs/remotes when applied to --branches, --tags, or --remotes, respectively, and they must begin with refs/ when applied to --glob or --all. If a trailing /* is intended, it must be given explicitly.
Omit any commit that introduces the same change as another commit on the other side when the set of commits are limited with symmetric difference.
For example, if you have two branches, A and B, a usual way to list all commits on only one side of them is with --left-right (see the example below in the description of the --left-right option). However, it shows the commits that were cherry-picked from the other branch (for example, 3rd on b may be cherry-picked from branch A). With this option, such pairs of commits are excluded from the output.
List only commits on the respective side of a symmetric difference, i.e. only those which would be marked < resp. > by --left-right.
For example, --cherry-pick --right-only A...B omits those commits from B which are in A or are patch-equivalent to a commit in A. In other words, this lists the + commits from git cherry A B. More precisely, --cherry-pick --right-only --no-merges gives the exact list.
Instead of walking the commit ancestry chain, walk reflog entries from the most recent one to older ones. When this option is used you cannot specify commits to exclude (that is, ^commit, commit1..commit2, and commit1...commit2 notations cannot be used).
With --pretty format other than oneline and reference (for obvious reasons), this causes the output to have two extra lines of information taken from the reflog. The reflog designator in the output may be shown as ref@{<Nth>} (where <Nth> is the reverse-chronological index in the reflog) or as ref@{<timestamp>} (with the <timestamp> for that entry), depending on a few rules:
Under --pretty=oneline, the commit message is prefixed with this information on the same line. This option cannot be combined with --reverse. See also the section called “git-reflog(1)”.
Under --pretty=reference, this information will not be shown at all.
Sometimes you are only interested in parts of the history, for example the commits modifying a particular <path>. But there are two parts of History Simplification, one part is selecting the commits and the other is how to do it, as there are various strategies to simplify the history.
The following options select the commits to be shown:
Note that extra commits can be shown to give a meaningful history.
The following options affect the way the simplification is performed:
A more detailed explanation follows.
Suppose you specified foo as the <paths>. We shall call commits that modify foo !TREESAME, and the rest TREESAME. (In a diff filtered for foo, they look different and equal, respectively.)
In the following, we will always refer to the same example history to illustrate the differences between simplification settings. We assume that you are filtering for a file foo in this commit graph:
.-A---M---N---O---P---Q
/ / / / / /
I B C D E Y
\ / / / / /
`-------------' XThe horizontal line of history A---Q is taken to be the first parent of each merge. The commits are:
rev-list walks backwards through history, including or excluding commits based on whether --full-history and/or parent rewriting (via --parents or --children) are used. The following settings are available.
Commits are included if they are not TREESAME to any parent (though this can be changed, see --sparse below). If the commit was a merge, and it was TREESAME to one parent, follow only that parent. (Even if there are several TREESAME parents, follow only one of them.) Otherwise, follow all parents.
This results in:
.-A---N---O
/ / /
I---------DNote how the rule to only follow the TREESAME parent, if one is available, removed B from consideration entirely. C was considered via N, but is TREESAME. Root commits are compared to an empty tree, so I is !TREESAME.
Parent/child relations are only visible with --parents, but that does not affect the commits selected in default mode, so we have shown the parent lines.
This mode differs from the default in one point: always follow all parents of a merge, even if it is TREESAME to one of them. Even if more than one side of the merge has commits that are included, this does not imply that the merge itself is! In the example, we get
I A B N D O P Q
M was excluded because it is TREESAME to both parents. E, C and B were all walked, but only B was !TREESAME, so the others do not appear.
Note that without parent rewriting, it is not really possible to talk about the parent/child relationships between the commits, so we show them disconnected.
Ordinary commits are only included if they are !TREESAME (though this can be changed, see --sparse below).
Merges are always included. However, their parent list is rewritten: Along each parent, prune away commits that are not included themselves. This results in
.-A---M---N---O---P---Q
/ / / / /
I B / D /
\ / / / /
`-------------'Compare to --full-history without rewriting above. Note that E was pruned away because it is TREESAME, but the parent list of P was rewritten to contain E's parent I. The same happened for C and N, and X, Y and Q.
In addition to the above settings, you can change whether TREESAME affects inclusion:
All commits that are walked are included.
Note that without --full-history, this still simplifies merges: if one of the parents is TREESAME, we follow only that one, so the other sides of the merge are never walked.
First, build a history graph in the same way that --full-history with parent rewriting does (see above).
Then simplify each commit C to its replacement C' in the final history according to the following rules:
The effect of this is best shown by way of comparing to --full-history with parent rewriting. The example turns into:
.-A---M---N---O
/ / /
I B D
\ / /
`---------'Note the major differences in N, P, and Q over --full-history:
There is another simplification mode available:
Limit the displayed commits to those which are an ancestor of <commit>, or which are a descendant of <commit>, or are <commit> itself.
As an example use case, consider the following commit history:
D---E-------F
/ \ \
B---C---G---H---I---J
/ \
A-------K---------------L--MA regular D..M computes the set of commits that are ancestors of M, but excludes the ones that are ancestors of D. This is useful to see what happened to the history leading to M since D, in the sense that what does M have that did not exist in D. The result in this example would be all the commits, except A and B (and D itself, of course).
When we want to find out what commits in M are contaminated with the bug introduced by D and need fixing, however, we might want to view only the subset of D..M that are actually descendants of D, i.e. excluding C and K. This is exactly what the --ancestry-path option does. Applied to the D..M range, it results in:
E-------F
\ \
G---H---I---J
\
L--MWe can also use --ancestry-path=D instead of --ancestry-path which means the same thing when applied to the D..M range but is just more explicit.
If we instead are interested in a given topic within this range, and all commits affected by that topic, we may only want to view the subset of D..M which contain that topic in their ancestry path. So, using --ancestry-path=H D..M for example would result in:
E
\
C---G---H---I---J
\
L--MWhereas --ancestry-path=K D..M would result in
K---------------L--M
Before discussing another option, --show-pulls, we need to create a new example history.
A common problem users face when looking at simplified history is that a commit they know changed a file somehow does not appear in the file's simplified history. Let's demonstrate a new example and show how options such as --full-history and --simplify-merges works in that case:
.-A---M-----C--N---O---P
/ / \ \ \/ / /
I B \ R-'`-Z' /
\ / \/ /
\ / /\ /
`---X--' `---Y--'For this example, suppose I created file.txt which was modified by A, B, and X in different ways. The single-parent commits C, Z, and Y do not change file.txt. The merge commit M was created by resolving the merge conflict to include both changes from A and B and hence is not TREESAME to either. The merge commit R, however, was created by ignoring the contents of file.txt at M and taking only the contents of file.txt at X. Hence, R is TREESAME to X but not M. Finally, the natural merge resolution to create N is to take the contents of file.txt at R, so N is TREESAME to R but not C. The merge commits O and P are TREESAME to their first parents, but not to their second parents, Z and Y respectively.
When using the default mode, N and R both have a TREESAME parent, so those edges are walked and the others are ignored. The resulting history graph is:
I---X
When using --full-history, Git walks every edge. This will discover the commits A and B and the merge M, but also will reveal the merge commits O and P. With parent rewriting, the resulting graph is:
.-A---M--------N---O---P
/ / \ \ \/ / /
I B \ R-'`--' /
\ / \/ /
\ / /\ /
`---X--' `------'Here, the merge commits O and P contribute extra noise, as they did not actually contribute a change to file.txt. They only merged a topic that was based on an older version of file.txt. This is a common issue in repositories using a workflow where many contributors work in parallel and merge their topic branches along a single trunk: many unrelated merges appear in the --full-history results.
When using the --simplify-merges option, the commits O and P disappear from the results. This is because the rewritten second parents of O and P are reachable from their first parents. Those edges are removed and then the commits look like single-parent commits that are TREESAME to their parent. This also happens to the commit N, resulting in a history view as follows:
.-A---M--.
/ / \
I B R
\ / /
\ / /
`---X--'In this view, we see all of the important single-parent changes from A, B, and X. We also see the carefully-resolved merge M and the not-so-carefully-resolved merge R. This is usually enough information to determine why the commits A and B "disappeared" from history in the default view. However, there are a few issues with this approach.
The first issue is performance. Unlike any previous option, the --simplify-merges option requires walking the entire commit history before returning a single result. This can make the option difficult to use for very large repositories.
The second issue is one of auditing. When many contributors are working on the same repository, it is important which merge commits introduced a change into an important branch. The problematic merge R above is not likely to be the merge commit that was used to merge into an important branch. Instead, the merge N was used to merge R and X into the important branch. This commit may have information about why the change X came to override the changes from A and B in its commit message.
In addition to the commits shown in the default history, show each merge commit that is not TREESAME to its first parent but is TREESAME to a later parent.
When a merge commit is included by --show-pulls, the merge is treated as if it "pulled" the change from another branch. When using --show-pulls on this example (and no other options) the resulting graph is:
I---X---R---N
Here, the merge commits R and N are included because they pulled the commits X and R into the base branch, respectively. These merges are the reason the commits A and B do not appear in the default history.
When --show-pulls is paired with --simplify-merges, the graph includes all of the necessary information:
.-A---M--. N
/ / \ /
I B R
\ / /
\ / /
`---X--'Notice that since M is reachable from R, the edge from N to M was simplified away. However, N still appears in the history as an important commit because it "pulled" the change R into the main branch.
The --simplify-by-decoration option allows you to view only the big picture of the topology of the history, by omitting commits that are not referenced by tags. Commits are marked as !TREESAME (in other words, kept after history simplification rules described above) if (1) they are referenced by tags, or (2) they change the contents of the paths given on the command line. All other commits are marked as TREESAME (subject to be simplified away).
By default, the commits are shown in reverse chronological order.
Show no parents before all of its children are shown, and avoid showing commits on multiple lines of history intermixed.
For example, in a commit history like this:
---1----2----4----7
\ \
3----5----6----8---where the numbers denote the order of commit timestamps, git rev-list and friends with --date-order show the commits in the timestamp order: 8 7 6 5 4 3 2 1.
With --topo-order, they would show 8 6 5 3 7 4 2 1 (or 8 7 4 2 6 5 3 1); some older commits are shown before newer ones in order to avoid showing the commits from two parallel development track mixed together.
These options are mostly targeted for packing of Git repositories.
Pretty-print the contents of the commit logs in a given format, where <format> can be one of oneline, short, medium, full, fuller, reference, email, raw, format:<string> and tformat:<string>. When <format> is none of the above, and has %placeholder in it, it acts as if --pretty=tformat:<format> were given.
See the "PRETTY FORMATS" section for some additional details for each format. When =<format> part is omitted, it defaults to medium.
Note: you can specify the default pretty format in the repository configuration (see the section called “git-config(1)”).
Instead of showing the full 40-byte hexadecimal commit object name, show a prefix that names the object uniquely. "--abbrev=<n>" (which also modifies diff output, if it is displayed) option can be used to specify the minimum length of the prefix.
This should make "--pretty=oneline" a whole lot more readable for people using 80-column terminals.
Perform a tab expansion (replace each tab with enough spaces to fill to the next display column that is a multiple of <n>) in the log message before showing it in the output. --expand-tabs is a short-hand for --expand-tabs=8, and --no-expand-tabs is a short-hand for --expand-tabs=0, which disables tab expansion.
By default, tabs are expanded in pretty formats that indent the log message by 4 spaces (i.e. medium, which is the default, full, and fuller).
Show the notes (see the section called “git-notes(1)”) that annotate the commit, when showing the commit log message. This is the default for git log, git show and git whatchanged commands when there is no --pretty, --format, or --oneline option given on the command line.
By default, the notes shown are from the notes refs listed in the core.notesRef and notes.displayRef variables (or corresponding environment overrides). See the section called “git-config(1)” for more details.
With an optional <ref> argument, use the ref to find the notes to display. The ref can specify the full refname when it begins with refs/notes/; when it begins with notes/, refs/ and otherwise refs/notes/ is prefixed to form the full name of the ref.
Multiple --notes options can be combined to control which notes are being displayed. Examples: "--notes=foo" will show only notes from "refs/notes/foo"; "--notes=foo --notes" will show both notes from "refs/notes/foo" and from the default notes ref(s).
Only takes effect for dates shown in human-readable format, such as when using --pretty. log.date config variable sets a default value for the log command's --date option. By default, dates are shown in the original time zone (either committer's or author's). If -local is appended to the format (e.g., iso-local), the user's local time zone is used instead.
--date=relative shows dates relative to the current time, e.g. 2 hours ago. The -local option has no effect for --date=relative.
--date=local is an alias for --date=default-local.
--date=iso (or --date=iso8601) shows timestamps in a ISO 8601-like format. The differences to the strict ISO 8601 format are:
--date=iso-strict (or --date=iso8601-strict) shows timestamps in strict ISO 8601 format.
--date=rfc (or --date=rfc2822) shows timestamps in RFC 2822 format, often found in email messages.
--date=short shows only the date, but not the time, in YYYY-MM-DD format.
--date=raw shows the date as seconds since the epoch (1970-01-01 00:00:00 UTC), followed by a space, and then the timezone as an offset from UTC (a + or - with four digits; the first two are hours, and the second two are minutes). I.e., as if the timestamp were formatted with strftime("%s %z")). Note that the -local option does not affect the seconds-since-epoch value (which is always measured in UTC), but does switch the accompanying timezone value.
--date=human shows the timezone if the timezone does not match the current time-zone, and doesn't print the whole date if that matches (ie skip printing year for dates that are "this year", but also skip the whole date itself if it's in the last few days and we can just say what weekday it was). For older dates the hour and minute is also omitted.
--date=unix shows the date as a Unix epoch timestamp (seconds since 1970). As with --raw, this is always in UTC and therefore -local has no effect.
--date=format:... feeds the format ... to your system strftime, except for %s, %z, and %Z, which are handled internally. Use --date=format:%c to show the date in your system locale's preferred format. See the strftime manual for a complete list of format placeholders. When using -local, the correct syntax is --date=format-local:....
--date=default is the default format, and is based on ctime(3) output. It shows a single line with three-letter day of the week, three-letter month, day-of-month, hour-minute-seconds in "HH:MM:SS" format, followed by 4-digit year, plus timezone information, unless the local time zone is used, e.g. Thu Jan 1 00:00:00 1970 +0000.
Mark which side of a symmetric difference a commit is reachable from. Commits from the left side are prefixed with < and those from the right with >. If combined with --boundary, those commits are prefixed with -.
For example, if you have this topology:
y---b---b branch B
/ \ /
/ .
/ / \
o---x---a---a branch Ayou would get an output like this:
$ git rev-list --left-right --boundary --pretty=oneline A...B
>bbbbbbb... 3rd on b
>bbbbbbb... 2nd on b
<aaaaaaa... 3rd on a
<aaaaaaa... 2nd on a
-yyyyyyy... 1st on b
-xxxxxxx... 1st on aDraw a text-based graphical representation of the commit history on the left hand side of the output. This may cause extra lines to be printed in between commits, in order for the graph history to be drawn properly. Cannot be combined with --no-walk.
This enables parent rewriting, see History Simplification above.
This implies the --topo-order option by default, but the --date-order option may also be specified.
When there are no conflicts, the output of this command is usable as input to git update-ref --stdin. It is of the form:
update refs/heads/branch1 ${NEW_branch1_HASH} ${OLD_branch1_HASH}
update refs/heads/branch2 ${NEW_branch2_HASH} ${OLD_branch2_HASH}
update refs/heads/branch3 ${NEW_branch3_HASH} ${OLD_branch3_HASH}where the number of refs updated depends on the arguments passed and the shape of the history being replayed. When using --advance, the number of refs updated is always one, but for --onto, it can be one or more (rebasing multiple branches simultaneously is supported).
For a successful, non-conflicted replay, the exit status is 0. When the replay has conflicts, the exit status is 1. If the replay is not able to complete (or start) due to some kind of error, the exit status is something other than 0 or 1.
To simply rebase mybranch onto target:
$ git replay --onto target origin/main..mybranch
update refs/heads/mybranch ${NEW_mybranch_HASH} ${OLD_mybranch_HASH}To cherry-pick the commits from mybranch onto target:
$ git replay --advance target origin/main..mybranch
update refs/heads/target ${NEW_target_HASH} ${OLD_target_HASH}Note that the first two examples replay the exact same commits and on top of the exact same new base, they only differ in that the first provides instructions to make mybranch point at the new commits and the second provides instructions to make target point at them.
What if you have a stack of branches, one depending upon another, and you'd really like to rebase the whole set?
$ git replay --contained --onto origin/main origin/main..tipbranch
update refs/heads/branch1 ${NEW_branch1_HASH} ${OLD_branch1_HASH}
update refs/heads/branch2 ${NEW_branch2_HASH} ${OLD_branch2_HASH}
update refs/heads/tipbranch ${NEW_tipbranch_HASH} ${OLD_tipbranch_HASH}When calling git replay, one does not need to specify a range of commits to replay using the syntax A..B; any range expression will do:
$ git replay --onto origin/main ^base branch1 branch2 branch3
update refs/heads/branch1 ${NEW_branch1_HASH} ${OLD_branch1_HASH}
update refs/heads/branch2 ${NEW_branch2_HASH} ${OLD_branch2_HASH}
update refs/heads/branch3 ${NEW_branch3_HASH} ${OLD_branch3_HASH}This will simultaneously rebase branch1, branch2, and branch3, all commits they have since base, playing them on top of origin/main. These three branches may have commits on top of base that they have in common, but that does not need to be the case.
Part of the the section called “git(1)” suite
Generate a request asking your upstream project to pull changes into their tree. The request, printed to the standard output, begins with the branch description, summarizes the changes, and indicates from where they can be pulled.
The upstream project is expected to have the commit named by <start> and the output asks it to integrate the changes you made since that commit, up to the commit named by <end>, by visiting the repository named by <URL>.
Commit to end at (defaults to HEAD). This names the commit at the tip of the history you are asking to be pulled.
When the repository named by <URL> has the commit at a tip of a ref that is different from the ref you have locally, you can use the <local>:<remote> syntax, to have its local name, a colon :, and its remote name.
Imagine that you built your work on your master branch on top of the v1.0 release, and want it to be integrated into the project. First you push that change to your public repository for others to see:
git push https://git.ko.xz/project master
Then, you run this command:
git request-pull v1.0 https://git.ko.xz/project master
which will produce a request to the upstream, summarizing the changes between the v1.0 release and your master, to pull it from your public repository.
If you pushed your change to a branch whose name is different from the one you have locally, e.g.
git push https://git.ko.xz/project master:for-linus
then you can ask that to be pulled with
git request-pull v1.0 https://git.ko.xz/project master:for-linus
Part of the the section called “git(1)” suite
In a workflow employing relatively long lived topic branches, the developer sometimes needs to resolve the same conflicts over and over again until the topic branches are done (either merged to the "release" branch, or sent out and accepted upstream).
This command assists the developer in this process by recording conflicted automerge results and corresponding hand resolve results on the initial manual merge, and applying previously recorded hand resolutions to their corresponding automerge results.
You need to set the configuration variable rerere.enabled in order to enable this command.
Normally, git rerere is run without arguments or user-intervention. However, it has several commands that allow it to interact with its working state.
When your topic branch modifies an overlapping area that your master branch (or upstream) touched since your topic branch forked from it, you may want to test it with the latest master, even before your topic branch is ready to be pushed upstream:
o---*---o topic
/
o---o---o---*---o---o masterFor such a test, you need to merge master and topic somehow. One way to do it is to pull master into the topic branch:
$ git switch topic
$ git merge master
o---*---o---+ topic
/ /
o---o---o---*---o---o masterThe commits marked with * touch the same area in the same file; you need to resolve the conflicts when creating the commit marked with +. Then you can test the result to make sure your work-in-progress still works with what is in the latest master.
After this test merge, there are two ways to continue your work on the topic. The easiest is to build on top of the test merge commit +, and when your work in the topic branch is finally ready, pull the topic branch into master, and/or ask the upstream to pull from you. By that time, however, the master or the upstream might have been advanced since the test merge +, in which case the final commit graph would look like this:
$ git switch topic
$ git merge master
$ ... work on both topic and master branches
$ git switch master
$ git merge topic
o---*---o---+---o---o topic
/ / \
o---o---o---*---o---o---o---o---+ masterWhen your topic branch is long-lived, however, your topic branch would end up having many such "Merge from master" commits on it, which would unnecessarily clutter the development history. Readers of the Linux kernel mailing list may remember that Linus complained about such too frequent test merges when a subsystem maintainer asked to pull from a branch full of "useless merges".
As an alternative, to keep the topic branch clean of test merges, you could blow away the test merge, and keep building on top of the tip before the test merge:
$ git switch topic
$ git merge master
$ git reset --hard HEAD^ ;# rewind the test merge
$ ... work on both topic and master branches
$ git switch master
$ git merge topic
o---*---o-------o---o topic
/ \
o---o---o---*---o---o---o---o---+ masterThis would leave only one merge commit when your topic branch is finally ready and merged into the master branch. This merge would require you to resolve the conflict, introduced by the commits marked with *. However, this conflict is often the same conflict you resolved when you created the test merge you blew away. git rerere helps you resolve this final conflicted merge using the information from your earlier hand resolve.
Running the git rerere command immediately after a conflicted automerge records the conflicted working tree files, with the usual conflict markers <<<<<<<, =======, and >>>>>>> in them. Later, after you are done resolving the conflicts, running git rerere again will record the resolved state of these files. Suppose you did this when you created the test merge of master into the topic branch.
Next time, after seeing the same conflicted automerge, running git rerere will perform a three-way merge between the earlier conflicted automerge, the earlier manual resolution, and the current conflicted automerge. If this three-way merge resolves cleanly, the result is written out to your working tree file, so you do not have to manually resolve it. Note that git rerere leaves the index file alone, so you still need to do the final sanity checks with git diff (or git diff -c) and git add when you are satisfied.
As a convenience measure, git merge automatically invokes git rerere upon exiting with a failed automerge and git rerere records the hand resolve when it is a new conflict, or reuses the earlier hand resolve when it is not. git commit also invokes git rerere when committing a merge result. What this means is that you do not have to do anything special yourself (besides enabling the rerere.enabled config variable).
In our example, when you do the test merge, the manual resolution is recorded, and it will be reused when you do the actual merge later with the updated master and topic branch, as long as the recorded resolution is still applicable.
The information git rerere records is also used when running git rebase. After blowing away the test merge and continuing development on the topic branch:
o---*---o-------o---o topic
/
o---o---o---*---o---o---o---o master
$ git rebase master topic
o---*---o-------o---o topic
/
o---o---o---*---o---o---o---o masteryou could run git rebase master topic, to bring yourself up to date before your topic is ready to be sent upstream. This would result in falling back to a three-way merge, and it would conflict the same way as the test merge you resolved earlier. git rerere will be run by git rebase to help you resolve this conflict.
[NOTE] git rerere relies on the conflict markers in the file to detect the conflict. If the file already contains lines that look the same as lines with conflict markers, git rerere may fail to record a conflict resolution. To work around this, the conflict-marker-size setting in the section called “gitattributes(5)” can be used.
Part of the the section called “git(1)” suite
gitreset[-q] [<tree-ish>] [--] <pathspec>…
gitreset[-q] [--pathspec-from-file=<file> [--pathspec-file-nul]] [<tree-ish>]
gitreset(--patch|-p) [<tree-ish>] [--] [<pathspec>…]
gitreset[--soft|--mixed[-N] |--hard|--merge|--keep] [-q] [<commit>]
In the first three forms, copy entries from <tree-ish> to the index. In the last form, set the current branch head (HEAD) to <commit>, optionally modifying index and working tree to match. The <tree-ish>/<commit> defaults to HEAD in all forms.
These forms reset the index entries for all paths that match the <pathspec> to their state at <tree-ish>. (It does not affect the working tree or the current branch.)
This means that git reset <pathspec> is the opposite of git add <pathspec>. This command is equivalent to git restore [--source=<tree-ish>] --staged <pathspec>....
After running git reset <pathspec> to update the index entry, you can use the section called “git-restore(1)” to check the contents out of the index to the working tree. Alternatively, using the section called “git-restore(1)” and specifying a commit with --source, you can copy the contents of a path out of a commit to the index and to the working tree in one go.
Interactively select hunks in the difference between the index and <tree-ish> (defaults to HEAD). The chosen hunks are applied in reverse to the index.
This means that git reset -p is the opposite of git add -p, i.e. you can use it to selectively reset hunks. See the "Interactive Mode" section of the section called “git-add(1)” to learn how to operate the --patch mode.
This form resets the current branch head to <commit> and possibly updates the index (resetting it to the tree of <commit>) and the working tree depending on <mode>. Before the operation, ORIG_HEAD is set to the tip of the current branch. If <mode> is omitted, defaults to --mixed. The <mode> must be one of the following:
Resets the index but not the working tree (i.e., the changed files are preserved but not marked for commit) and reports what has not been updated. This is the default action.
If -N is specified, removed paths are marked as intent-to-add (see the section called “git-add(1)”).
Resets the index and updates the files in the working tree that are different between <commit> and HEAD, but keeps those which are different between the index and working tree (i.e. which have changes which have not been added). If a file that is different between <commit> and the index has unstaged changes, reset is aborted.
In other words, --merge does something like a git read-tree -u -m <commit>, but carries forward unmerged index entries.
See "Reset, restore and revert" in the section called “git(1)” for the differences between the three commands.
Limits the paths affected by the operation.
For more details, see the pathspec entry in the section called “gitglossary(7)”.
$ edit$ git add frotz.c filfre.c $ mailx
$ git reset
$ git pull git://info.example.com/ nitfol
You are happily working on something, and find the changes in these files are in good order. You do not want to see them when you run git diff, because you plan to work on other files and changes with these files are distracting. | |
Somebody asks you to pull, and the changes sound worthy of merging. | |
However, you already dirtied the index (i.e. your index does not match the HEAD commit). But you know the pull you are going to make does not affect frotz.c or filfre.c, so you revert the index changes for these two files. Your changes in working tree remain there. | |
Then you can pull and merge, leaving frotz.c and filfre.c changes still in the working tree. |
$ git commit ... $ git reset --soft HEAD^$ edit
$ git commit -a -c ORIG_HEAD
This is most often done when you remembered what you just committed is incomplete, or you misspelled your commit message, or both. Leaves working tree as it was before "reset". | |
Make corrections to working tree files. | |
"reset" copies the old head to .git/ORIG_HEAD; redo the commit by starting with its log message. If you do not need to edit the message further, you can give -C option instead. See also the --amend option to the section called “git-commit(1)”. |
$ git branch topic/wip$ git reset --hard HEAD~3
$ git switch topic/wip
$ git commit ... $ git reset --hard HEAD~3
The last three commits (HEAD, HEAD^, and HEAD~2) were bad and you do not want to ever see them again. Do not do this if you have already given these commits to somebody else. (See the "RECOVERING FROM UPSTREAM REBASE" section in the section called “git-rebase(1)” for the implications of doing so.) |
$ git pullAuto-merging nitfol CONFLICT (content): Merge conflict in nitfol Automatic merge failed; fix conflicts and then commit the result. $ git reset --hard
$ git pull . topic/branch
Updating from 41223... to 13134... Fast-forward $ git reset --hard ORIG_HEAD
Try to update from the upstream resulted in a lot of conflicts; you were not ready to spend a lot of time merging right now, so you decide to do that later. | |
"pull" has not made merge commit, so git reset --hard which is a synonym for git reset --hard HEAD clears the mess from the index file and the working tree. | |
Merge a topic branch into the current branch, which resulted in a fast-forward. | |
But you decided that the topic branch is not ready for public consumption yet. "pull" or "merge" always leaves the original tip of the current branch in ORIG_HEAD, so resetting hard to it brings your index file and the working tree back to that state, and resets the tip of the branch to that commit. |
$ git pullAuto-merging nitfol Merge made by recursive. nitfol | 20 +++++---- ... $ git reset --merge ORIG_HEAD
Even if you may have local modifications in your working tree, you can safely say git pull when you know that the change in the other branch does not overlap with them. | |
After inspecting the result of the merge, you may find that the change in the other branch is unsatisfactory. Running git reset --hard ORIG_HEAD will let you go back to where you were, but it will discard your local changes, which you do not want. git reset --merge keeps your local changes. |
Suppose you are interrupted by an urgent fix request while you are in the middle of a large change. The files in your working tree are not in any shape to be committed yet, but you need to get to the other branch for a quick bugfix.
$ git switch feature ;# you were working in "feature" branch and $ work work work ;# got interrupted $ git commit -a -m "snapshot WIP"$ git switch master $ fix fix fix $ git commit ;# commit with real log $ git switch feature $ git reset --soft HEAD^ ;# go back to WIP state
$ git reset
This commit will get blown away so a throw-away log message is OK. | |
This removes the WIP commit from the commit history, and sets your working tree to the state just before you made that snapshot. | |
At this point the index file still has all the WIP changes you committed as snapshot WIP. This updates the index to show your WIP files as uncommitted. See also the section called “git-stash(1)”. |
Suppose you have added a file to your index, but later decide you do not want to add it to your commit. You can remove the file from the index while keeping your changes with git reset.
$ git reset -- frotz.c$ git commit -m "Commit files in index"
$ git add frotz.c
Suppose you are working on something and you commit it, and then you continue working a bit more, but now you think that what you have in your working tree should be in another branch that has nothing to do with what you committed previously. You can start a new branch and reset it while keeping the changes in your working tree.
$ git tag start $ git switch -c branch1 $ edit $ git commit ...$ edit $ git switch -c branch2
$ git reset --keep start
This commits your first edits in branch1. | |
In the ideal world, you could have realized that the earlier commit did not belong to the new topic when you created and switched to branch2 (i.e. git switch -c branch2 start), but nobody is perfect. | |
But you can use reset --keep to remove the unwanted commit after you switched to branch2. |
Suppose that you have created lots of logically separate changes and committed them together. Then, later you decide that it might be better to have each logical chunk associated with its own commit. You can use git reset to rewind history without changing the contents of your local files, and then successively use git add -p to interactively select which hunks to include into each commit, using git commit -c to pre-populate the commit message.
$ git reset -N HEAD^$ git add -p
$ git diff --cached
$ git commit -c HEAD@{1}
...
$ git add ...
$ git diff --cached
$ git commit ...
First, reset the history back one commit so that we remove the original commit, but leave the working tree with all the changes. The -N ensures that any new files added with HEAD are still marked so that git add -p will find them. | |
Next, we interactively select diff hunks to add using the git add -p facility. This will ask you about each diff hunk in sequence and you can use simple commands such as "yes, include this", "No don't include this" or even the very powerful "edit" facility. | |
Once satisfied with the hunks you want to include, you should verify what has been prepared for the first commit by using git diff --cached. This shows all the changes that have been moved into the index and are about to be committed. | |
Next, commit the changes stored in the index. The -c option specifies to pre-populate the commit message from the original message that you started with in the first commit. This is helpful to avoid retyping it. The HEAD@{1} is a special notation for the commit that HEAD used to be at prior to the original reset commit (1 change ago). See the section called “git-reflog(1)” for more details. You may also use any other valid commit reference. | |
You can repeat steps 2-4 multiple times to break the original code into any number of commits. | |
Now you've split out many of the changes into their own commits, and might no longer use the patch mode of git add, in order to select all remaining uncommitted changes. | |
Once again, check to verify that you've included what you want to. You may also wish to verify that git diff doesn't show any remaining changes to be committed later. | |
And finally create the final commit. |
The tables below show what happens when running:
git reset --option target
to reset the HEAD to another commit (target) with the different reset options depending on the state of the files.
In these tables, A, B, C and D are some different states of a file. For example, the first line of the first table means that if a file is in state A in the working tree, in state B in the index, in state C in HEAD and in state D in the target, then git reset --soft target will leave the file in the working tree in state A and in the index in state B. It resets (i.e. moves) the HEAD (i.e. the tip of the current branch, if you are on one) to target (which has the file in state D).
working index HEAD target working index HEAD
----------------------------------------------------
A B C D --soft A B D
--mixed A D D
--hard D D D
--merge (disallowed)
--keep (disallowed)working index HEAD target working index HEAD
----------------------------------------------------
A B C C --soft A B C
--mixed A C C
--hard C C C
--merge (disallowed)
--keep A C Cworking index HEAD target working index HEAD
----------------------------------------------------
B B C D --soft B B D
--mixed B D D
--hard D D D
--merge D D D
--keep (disallowed)working index HEAD target working index HEAD
----------------------------------------------------
B B C C --soft B B C
--mixed B C C
--hard C C C
--merge C C C
--keep B C Cworking index HEAD target working index HEAD
----------------------------------------------------
B C C D --soft B C D
--mixed B D D
--hard D D D
--merge (disallowed)
--keep (disallowed)working index HEAD target working index HEAD
----------------------------------------------------
B C C C --soft B C C
--mixed B C C
--hard C C C
--merge B C C
--keep B C Cgit reset --merge is meant to be used when resetting out of a conflicted merge. Any mergy operation guarantees that the working tree file that is involved in the merge does not have a local change with respect to the index before it starts, and that it writes the result out to the working tree. So if we see some difference between the index and the target and also between the index and the working tree, then it means that we are not resetting out from a state that a mergy operation left after failing with a conflict. That is why we disallow --merge option in this case.
git reset --keep is meant to be used when removing some of the last commits in the current branch while keeping changes in the working tree. If there could be conflicts between the changes in the commit we want to remove and the changes in the working tree we want to keep, the reset is disallowed. That's why it is disallowed if there are both changes between the working tree and HEAD, and between HEAD and the target. To be safe, it is also disallowed when there are unmerged entries.
The following tables show what happens when there are unmerged entries:
working index HEAD target working index HEAD
----------------------------------------------------
X U A B --soft (disallowed)
--mixed X B B
--hard B B B
--merge B B B
--keep (disallowed)working index HEAD target working index HEAD
----------------------------------------------------
X U A A --soft (disallowed)
--mixed X A A
--hard A A A
--merge A A A
--keep (disallowed)X means any state and U means an unmerged index.
Part of the the section called “git(1)” suite
gitrestore[<options>] [--source=<tree>] [--staged] [--worktree] [--] <pathspec>…
gitrestore[<options>] [--source=<tree>] [--staged] [--worktree]--pathspec-from-file=<file> [--pathspec-file-nul]
gitrestore(-p|--patch) [<options>] [--source=<tree>] [--staged] [--worktree] [--] [<pathspec>…]
Restore specified paths in the working tree with some contents from a restore source. If a path is tracked but does not exist in the restore source, it will be removed to match the source.
The command can also be used to restore the content in the index with --staged, or restore both the working tree and the index with --staged --worktree.
By default, if --staged is given, the contents are restored from HEAD, otherwise from the index. Use --source to restore from a different commit.
See "Reset, restore and revert" in the section called “git(1)” for the differences between the three commands.
THIS COMMAND IS EXPERIMENTAL. THE BEHAVIOR MAY CHANGE.
Restore the working tree files with the content from the given tree. It is common to specify the source tree by naming a commit, branch or tag associated with it.
If not specified, the contents are restored from HEAD if --staged is given, otherwise from the index.
As a special case, you may use "<rev-A>...<rev-B>" as a shortcut for the merge base of <rev-A> and <rev-B> if there is exactly one merge base. You can leave out at most one of <rev-A>_ and <rev-B>, in which case it defaults to HEAD.
When restoring files in the working tree from the index, use stage #2 (ours) or #3 (theirs) for unmerged paths. This option cannot be used when checking out paths from a tree-ish (i.e. with the --source option).
Note that during git rebase and git pull --rebase, ours and theirs may appear swapped. See the explanation of the same options in the section called “git-checkout(1)” for details.
Limits the paths affected by the operation.
For more details, see the pathspec entry in the section called “gitglossary(7)”.
The following sequence switches to the master branch, reverts the Makefile to two revisions back, deletes hello.c by mistake, and gets it back from the index.
$ git switch master $ git restore --source master~2 Makefile$ rm -f hello.c $ git restore hello.c
If you want to restore all C source files to match the version in the index, you can say
$ git restore '*.c'
Note the quotes around *.c. The file hello.c will also be restored, even though it is no longer in the working tree, because the file globbing is used to match entries in the index (not in the working tree by the shell).
To restore all files in the current directory
$ git restore .
or to restore all working tree files with top pathspec magic (see the section called “gitglossary(7)”)
$ git restore :/
To restore a file in the index to match the version in HEAD (this is the same as using the section called “git-reset(1)”)
$ git restore --staged hello.c
or you can restore both the index and the working tree (this is the same as using the section called “git-checkout(1)”)
$ git restore --source=HEAD --staged --worktree hello.c
or the short form which is more practical but less readable:
$ git restore -s@ -SW hello.c
Part of the the section called “git(1)” suite
List commits that are reachable by following the parent links from the given commit(s), but exclude commits that are reachable from the one(s) given with a ^ in front of them. The output is given in reverse chronological order by default.
You can think of this as a set operation. Commits reachable from any of the commits given on the command line form a set, and then commits reachable from any of the ones given with ^ in front are subtracted from that set. The remaining commits are what comes out in the command's output. Various other options and paths parameters can be used to further limit the result.
Thus, the following command:
$ git rev-list foo bar ^baz
means "list all the commits which are reachable from foo or bar, but not from baz".
A special notation "<commit1>..<commit2>" can be used as a short-hand for "^<commit1> <commit2>". For example, either of the following may be used interchangeably:
$ git rev-list origin..HEAD $ git rev-list HEAD ^origin
Another special notation is "<commit1>…<commit2>" which is useful for merges. The resulting set of commits is the symmetric difference between the two operands. The following two commands are equivalent:
$ git rev-list A B --not $(git merge-base --all A B) $ git rev-list A...B
rev-list is an essential Git command, since it provides the ability to build and traverse commit ancestry graphs. For this reason, it has a lot of different options that enable it to be used by commands as different as git bisect and git repack.
Besides specifying a range of commits that should be listed using the special notations explained in the description, additional commit limiting may be applied.
Using more options generally further limits the output (e.g. --since=<date1> limits to commits newer than <date1>, and using it with --grep=<pattern> further limits to commits whose log message has a line that matches <pattern>), unless otherwise noted.
Note that these are applied before commit ordering and formatting options, such as --reverse.
Consider the limiting patterns to be Perl-compatible regular expressions.
Support for these types of regular expressions is an optional compile-time dependency. If Git wasn't compiled with support for them providing this option will cause it to die.
Show only commits which have at least (or at most) that many parent commits. In particular, --max-parents=1 is the same as --no-merges, --min-parents=2 is the same as --merges. --max-parents=0 gives all root commits and --min-parents=3 all octopus merges.
--no-min-parents and --no-max-parents reset these limits (to no limit) again. Equivalent forms are --min-parents=0 (any commit has 0 or more parents) and --max-parents=-1 (negative numbers denote no upper limit).
Do not include refs matching <glob-pattern> that the next --all, --branches, --tags, --remotes, or --glob would otherwise consider. Repetitions of this option accumulate exclusion patterns up to the next --all, --branches, --tags, --remotes, or --glob option (other options or arguments do not clear accumulated patterns).
The patterns given should not begin with refs/heads, refs/tags, or refs/remotes when applied to --branches, --tags, or --remotes, respectively, and they must begin with refs/ when applied to --glob or --all. If a trailing /* is intended, it must be given explicitly.
Omit any commit that introduces the same change as another commit on the other side when the set of commits are limited with symmetric difference.
For example, if you have two branches, A and B, a usual way to list all commits on only one side of them is with --left-right (see the example below in the description of the --left-right option). However, it shows the commits that were cherry-picked from the other branch (for example, 3rd on b may be cherry-picked from branch A). With this option, such pairs of commits are excluded from the output.
List only commits on the respective side of a symmetric difference, i.e. only those which would be marked < resp. > by --left-right.
For example, --cherry-pick --right-only A...B omits those commits from B which are in A or are patch-equivalent to a commit in A. In other words, this lists the + commits from git cherry A B. More precisely, --cherry-pick --right-only --no-merges gives the exact list.
Instead of walking the commit ancestry chain, walk reflog entries from the most recent one to older ones. When this option is used you cannot specify commits to exclude (that is, ^commit, commit1..commit2, and commit1...commit2 notations cannot be used).
With --pretty format other than oneline and reference (for obvious reasons), this causes the output to have two extra lines of information taken from the reflog. The reflog designator in the output may be shown as ref@{<Nth>} (where <Nth> is the reverse-chronological index in the reflog) or as ref@{<timestamp>} (with the <timestamp> for that entry), depending on a few rules:
Under --pretty=oneline, the commit message is prefixed with this information on the same line. This option cannot be combined with --reverse. See also the section called “git-reflog(1)”.
Under --pretty=reference, this information will not be shown at all.
Instead of being newline-delimited, each outputted object and its accompanying metadata is delimited using NUL bytes. Output is printed in the following form:
<OID> NUL [<token>=<value> NUL]...
Additional object metadata, such as object paths or boundary objects, is printed using the <token>=<value> form. Token values are printed as-is without any encoding/truncation. An OID entry never contains a = character and thus is used to signal the start of a new object record. Examples:
<OID> NUL <OID> NUL path=<path> NUL <OID> NUL boundary=yes NUL <OID> NUL missing=yes NUL [<token>=<value> NUL]...
This mode is only compatible with the --objects, --boundary, and --missing output options.
Sometimes you are only interested in parts of the history, for example the commits modifying a particular <path>. But there are two parts of History Simplification, one part is selecting the commits and the other is how to do it, as there are various strategies to simplify the history.
The following options select the commits to be shown:
Note that extra commits can be shown to give a meaningful history.
The following options affect the way the simplification is performed:
A more detailed explanation follows.
Suppose you specified foo as the <paths>. We shall call commits that modify foo !TREESAME, and the rest TREESAME. (In a diff filtered for foo, they look different and equal, respectively.)
In the following, we will always refer to the same example history to illustrate the differences between simplification settings. We assume that you are filtering for a file foo in this commit graph:
.-A---M---N---O---P---Q
/ / / / / /
I B C D E Y
\ / / / / /
`-------------' XThe horizontal line of history A---Q is taken to be the first parent of each merge. The commits are:
rev-list walks backwards through history, including or excluding commits based on whether --full-history and/or parent rewriting (via --parents or --children) are used. The following settings are available.
Commits are included if they are not TREESAME to any parent (though this can be changed, see --sparse below). If the commit was a merge, and it was TREESAME to one parent, follow only that parent. (Even if there are several TREESAME parents, follow only one of them.) Otherwise, follow all parents.
This results in:
.-A---N---O
/ / /
I---------DNote how the rule to only follow the TREESAME parent, if one is available, removed B from consideration entirely. C was considered via N, but is TREESAME. Root commits are compared to an empty tree, so I is !TREESAME.
Parent/child relations are only visible with --parents, but that does not affect the commits selected in default mode, so we have shown the parent lines.
This mode differs from the default in one point: always follow all parents of a merge, even if it is TREESAME to one of them. Even if more than one side of the merge has commits that are included, this does not imply that the merge itself is! In the example, we get
I A B N D O P Q
M was excluded because it is TREESAME to both parents. E, C and B were all walked, but only B was !TREESAME, so the others do not appear.
Note that without parent rewriting, it is not really possible to talk about the parent/child relationships between the commits, so we show them disconnected.
Ordinary commits are only included if they are !TREESAME (though this can be changed, see --sparse below).
Merges are always included. However, their parent list is rewritten: Along each parent, prune away commits that are not included themselves. This results in
.-A---M---N---O---P---Q
/ / / / /
I B / D /
\ / / / /
`-------------'Compare to --full-history without rewriting above. Note that E was pruned away because it is TREESAME, but the parent list of P was rewritten to contain E's parent I. The same happened for C and N, and X, Y and Q.
In addition to the above settings, you can change whether TREESAME affects inclusion:
All commits that are walked are included.
Note that without --full-history, this still simplifies merges: if one of the parents is TREESAME, we follow only that one, so the other sides of the merge are never walked.
First, build a history graph in the same way that --full-history with parent rewriting does (see above).
Then simplify each commit C to its replacement C' in the final history according to the following rules:
The effect of this is best shown by way of comparing to --full-history with parent rewriting. The example turns into:
.-A---M---N---O
/ / /
I B D
\ / /
`---------'Note the major differences in N, P, and Q over --full-history:
There is another simplification mode available:
Limit the displayed commits to those which are an ancestor of <commit>, or which are a descendant of <commit>, or are <commit> itself.
As an example use case, consider the following commit history:
D---E-------F
/ \ \
B---C---G---H---I---J
/ \
A-------K---------------L--MA regular D..M computes the set of commits that are ancestors of M, but excludes the ones that are ancestors of D. This is useful to see what happened to the history leading to M since D, in the sense that what does M have that did not exist in D. The result in this example would be all the commits, except A and B (and D itself, of course).
When we want to find out what commits in M are contaminated with the bug introduced by D and need fixing, however, we might want to view only the subset of D..M that are actually descendants of D, i.e. excluding C and K. This is exactly what the --ancestry-path option does. Applied to the D..M range, it results in:
E-------F
\ \
G---H---I---J
\
L--MWe can also use --ancestry-path=D instead of --ancestry-path which means the same thing when applied to the D..M range but is just more explicit.
If we instead are interested in a given topic within this range, and all commits affected by that topic, we may only want to view the subset of D..M which contain that topic in their ancestry path. So, using --ancestry-path=H D..M for example would result in:
E
\
C---G---H---I---J
\
L--MWhereas --ancestry-path=K D..M would result in
K---------------L--M
Before discussing another option, --show-pulls, we need to create a new example history.
A common problem users face when looking at simplified history is that a commit they know changed a file somehow does not appear in the file's simplified history. Let's demonstrate a new example and show how options such as --full-history and --simplify-merges works in that case:
.-A---M-----C--N---O---P
/ / \ \ \/ / /
I B \ R-'`-Z' /
\ / \/ /
\ / /\ /
`---X--' `---Y--'For this example, suppose I created file.txt which was modified by A, B, and X in different ways. The single-parent commits C, Z, and Y do not change file.txt. The merge commit M was created by resolving the merge conflict to include both changes from A and B and hence is not TREESAME to either. The merge commit R, however, was created by ignoring the contents of file.txt at M and taking only the contents of file.txt at X. Hence, R is TREESAME to X but not M. Finally, the natural merge resolution to create N is to take the contents of file.txt at R, so N is TREESAME to R but not C. The merge commits O and P are TREESAME to their first parents, but not to their second parents, Z and Y respectively.
When using the default mode, N and R both have a TREESAME parent, so those edges are walked and the others are ignored. The resulting history graph is:
I---X
When using --full-history, Git walks every edge. This will discover the commits A and B and the merge M, but also will reveal the merge commits O and P. With parent rewriting, the resulting graph is:
.-A---M--------N---O---P
/ / \ \ \/ / /
I B \ R-'`--' /
\ / \/ /
\ / /\ /
`---X--' `------'Here, the merge commits O and P contribute extra noise, as they did not actually contribute a change to file.txt. They only merged a topic that was based on an older version of file.txt. This is a common issue in repositories using a workflow where many contributors work in parallel and merge their topic branches along a single trunk: many unrelated merges appear in the --full-history results.
When using the --simplify-merges option, the commits O and P disappear from the results. This is because the rewritten second parents of O and P are reachable from their first parents. Those edges are removed and then the commits look like single-parent commits that are TREESAME to their parent. This also happens to the commit N, resulting in a history view as follows:
.-A---M--.
/ / \
I B R
\ / /
\ / /
`---X--'In this view, we see all of the important single-parent changes from A, B, and X. We also see the carefully-resolved merge M and the not-so-carefully-resolved merge R. This is usually enough information to determine why the commits A and B "disappeared" from history in the default view. However, there are a few issues with this approach.
The first issue is performance. Unlike any previous option, the --simplify-merges option requires walking the entire commit history before returning a single result. This can make the option difficult to use for very large repositories.
The second issue is one of auditing. When many contributors are working on the same repository, it is important which merge commits introduced a change into an important branch. The problematic merge R above is not likely to be the merge commit that was used to merge into an important branch. Instead, the merge N was used to merge R and X into the important branch. This commit may have information about why the change X came to override the changes from A and B in its commit message.
In addition to the commits shown in the default history, show each merge commit that is not TREESAME to its first parent but is TREESAME to a later parent.
When a merge commit is included by --show-pulls, the merge is treated as if it "pulled" the change from another branch. When using --show-pulls on this example (and no other options) the resulting graph is:
I---X---R---N
Here, the merge commits R and N are included because they pulled the commits X and R into the base branch, respectively. These merges are the reason the commits A and B do not appear in the default history.
When --show-pulls is paired with --simplify-merges, the graph includes all of the necessary information:
.-A---M--. N
/ / \ /
I B R
\ / /
\ / /
`---X--'Notice that since M is reachable from R, the edge from N to M was simplified away. However, N still appears in the history as an important commit because it "pulled" the change R into the main branch.
The --simplify-by-decoration option allows you to view only the big picture of the topology of the history, by omitting commits that are not referenced by tags. Commits are marked as !TREESAME (in other words, kept after history simplification rules described above) if (1) they are referenced by tags, or (2) they change the contents of the paths given on the command line. All other commits are marked as TREESAME (subject to be simplified away).
Limit output to the one commit object which is roughly halfway between included and excluded commits. Note that the bad bisection ref refs/bisect/bad is added to the included commits (if it exists) and the good bisection refs refs/bisect/good-* are added to the excluded commits (if they exist). Thus, supposing there are no refs in refs/bisect/, if
$ git rev-list --bisect foo ^bar ^baz
outputs midpoint, the output of the two commands
$ git rev-list foo ^midpoint
$ git rev-list midpoint ^bar ^bazwould be of roughly the same length. Finding the change which introduces a regression is thus reduced to a binary search: repeatedly generate and test new 'midpoint's until the commit chain is of length one.
This outputs all the commit objects between the included and excluded commits, ordered by their distance to the included and excluded commits. Refs in refs/bisect/ are not used. The farthest from them is displayed first. (This is the only one displayed by --bisect.)
This is useful because it makes it easy to choose a good commit to test when you want to avoid to test some of them for some reason (they may not compile for example).
This option can be used along with --bisect-vars, in this case, after all the sorted commit objects, there will be the same text as if --bisect-vars had been used alone.
By default, the commits are shown in reverse chronological order.
Show no parents before all of its children are shown, and avoid showing commits on multiple lines of history intermixed.
For example, in a commit history like this:
---1----2----4----7
\ \
3----5----6----8---where the numbers denote the order of commit timestamps, git rev-list and friends with --date-order show the commits in the timestamp order: 8 7 6 5 4 3 2 1.
With --topo-order, they would show 8 6 5 3 7 4 2 1 (or 8 7 4 2 6 5 3 1); some older commits are shown before newer ones in order to avoid showing the commits from two parallel development track mixed together.
These options are mostly targeted for packing of Git repositories.
Only useful with one of the --objects*; omits objects (usually blobs) from the list of printed objects. The <filter-spec> may be one of the following:
The form --filter=blob:none omits all blobs.
The form --filter=blob:limit=<n>[kmg] omits blobs of size at least n bytes or units. n may be zero. The suffixes k, m, and g can be used to name units in KiB, MiB, or GiB. For example, blob:limit=1k is the same as blob:limit=1024.
The form --filter=object:type=(tag|commit|tree|blob) omits all objects which are not of the requested type.
The form --filter=sparse:oid=<blob-ish> uses a sparse-checkout specification contained in the blob (or blob-expression) <blob-ish> to omit blobs that would not be required for a sparse checkout on the requested refs.
The form --filter=tree:<depth> omits all blobs and trees whose depth from the root tree is >= <depth> (minimum depth if an object is located at multiple depths in the commits traversed). <depth>=0 will not include any trees or blobs unless included explicitly in the command-line (or standard input when --stdin is used). <depth>=1 will include only the tree and blobs which are referenced directly by a commit reachable from <commit> or an explicitly-given object. <depth>=2 is like <depth>=1 while also including trees and blobs one more level removed from an explicitly-given commit or tree.
Note that the form --filter=sparse:path=<path> that wants to read from an arbitrary path on the filesystem has been dropped for security reasons.
Multiple --filter= flags can be specified to combine filters. Only objects which are accepted by every filter are included.
The form --filter=combine:<filter1>+<filter2>+…<filterN> can also be
used to combined several filters, but this is harder than just repeating
the --filter flag and is usually not necessary. Filters are joined by
+ and individual filters are %-encoded (i.e. URL-encoded).
Besides the + and % characters, the following characters are
reserved and also must be encoded: ~!@#$^&*()[]{}\;",<>?'`
as well as all characters with ASCII code <= 0x20, which includes
space and newline.
Other arbitrary characters can also be encoded. For instance, combine:tree:3+blob:none and combine:tree%3A3+blob%3Anone are equivalent.
A debug option to help with future "partial clone" development. This option specifies how missing objects are handled.
The form --missing=error requests that rev-list stop with an error if a missing object is encountered. This is the default action.
The form --missing=allow-any will allow object traversal to continue if a missing object is encountered. Missing objects will silently be omitted from the results.
The form --missing=allow-promisor is like allow-any, but will only allow object traversal to continue for EXPECTED promisor missing objects. Unexpected missing objects will raise an error.
The form --missing=print is like allow-any, but will also print a list of the missing objects. Object IDs are prefixed with a ? character.
The form --missing=print-info is like print, but will also print additional information about the missing object inferred from its containing object. The information is all printed on the same line with the missing object ID in the form: ?<oid> [<token>=<value>].... The <token>=<value> pairs containing additional information are separated from each other by a SP. The value is encoded in a token specific fashion, but SP or LF contained in value are always expected to be represented in such a way that the resulting encoded value does not have either of these two problematic bytes. Each <token>=<value> may be one of the following:
If some tips passed to the traversal are missing, they will be considered as missing too, and the traversal will ignore them. In case we cannot get their Object ID though, an error will be raised.
Using these options, the section called “git-rev-list(1)” will act similar to the more specialized family of commit log tools: the section called “git-log(1)”, the section called “git-show(1)”, and the section called “git-whatchanged(1)”
Pretty-print the contents of the commit logs in a given format, where <format> can be one of oneline, short, medium, full, fuller, reference, email, raw, format:<string> and tformat:<string>. When <format> is none of the above, and has %placeholder in it, it acts as if --pretty=tformat:<format> were given.
See the "PRETTY FORMATS" section for some additional details for each format. When =<format> part is omitted, it defaults to medium.
Note: you can specify the default pretty format in the repository configuration (see the section called “git-config(1)”).
Instead of showing the full 40-byte hexadecimal commit object name, show a prefix that names the object uniquely. "--abbrev=<n>" (which also modifies diff output, if it is displayed) option can be used to specify the minimum length of the prefix.
This should make "--pretty=oneline" a whole lot more readable for people using 80-column terminals.
Perform a tab expansion (replace each tab with enough spaces to fill to the next display column that is a multiple of <n>) in the log message before showing it in the output. --expand-tabs is a short-hand for --expand-tabs=8, and --no-expand-tabs is a short-hand for --expand-tabs=0, which disables tab expansion.
By default, tabs are expanded in pretty formats that indent the log message by 4 spaces (i.e. medium, which is the default, full, and fuller).
Only takes effect for dates shown in human-readable format, such as when using --pretty. log.date config variable sets a default value for the log command's --date option. By default, dates are shown in the original time zone (either committer's or author's). If -local is appended to the format (e.g., iso-local), the user's local time zone is used instead.
--date=relative shows dates relative to the current time, e.g. 2 hours ago. The -local option has no effect for --date=relative.
--date=local is an alias for --date=default-local.
--date=iso (or --date=iso8601) shows timestamps in a ISO 8601-like format. The differences to the strict ISO 8601 format are:
--date=iso-strict (or --date=iso8601-strict) shows timestamps in strict ISO 8601 format.
--date=rfc (or --date=rfc2822) shows timestamps in RFC 2822 format, often found in email messages.
--date=short shows only the date, but not the time, in YYYY-MM-DD format.
--date=raw shows the date as seconds since the epoch (1970-01-01 00:00:00 UTC), followed by a space, and then the timezone as an offset from UTC (a + or - with four digits; the first two are hours, and the second two are minutes). I.e., as if the timestamp were formatted with strftime("%s %z")). Note that the -local option does not affect the seconds-since-epoch value (which is always measured in UTC), but does switch the accompanying timezone value.
--date=human shows the timezone if the timezone does not match the current time-zone, and doesn't print the whole date if that matches (ie skip printing year for dates that are "this year", but also skip the whole date itself if it's in the last few days and we can just say what weekday it was). For older dates the hour and minute is also omitted.
--date=unix shows the date as a Unix epoch timestamp (seconds since 1970). As with --raw, this is always in UTC and therefore -local has no effect.
--date=format:... feeds the format ... to your system strftime, except for %s, %z, and %Z, which are handled internally. Use --date=format:%c to show the date in your system locale's preferred format. See the strftime manual for a complete list of format placeholders. When using -local, the correct syntax is --date=format-local:....
--date=default is the default format, and is based on ctime(3) output. It shows a single line with three-letter day of the week, three-letter month, day-of-month, hour-minute-seconds in "HH:MM:SS" format, followed by 4-digit year, plus timezone information, unless the local time zone is used, e.g. Thu Jan 1 00:00:00 1970 +0000.
Mark which side of a symmetric difference a commit is reachable from. Commits from the left side are prefixed with < and those from the right with >. If combined with --boundary, those commits are prefixed with -.
For example, if you have this topology:
y---b---b branch B
/ \ /
/ .
/ / \
o---x---a---a branch Ayou would get an output like this:
$ git rev-list --left-right --boundary --pretty=oneline A...B
>bbbbbbb... 3rd on b
>bbbbbbb... 2nd on b
<aaaaaaa... 3rd on a
<aaaaaaa... 2nd on a
-yyyyyyy... 1st on b
-xxxxxxx... 1st on aDraw a text-based graphical representation of the commit history on the left hand side of the output. This may cause extra lines to be printed in between commits, in order for the graph history to be drawn properly. Cannot be combined with --no-walk.
This enables parent rewriting, see History Simplification above.
This implies the --topo-order option by default, but the --date-order option may also be specified.
If the commit is a merge, and if the pretty-format is not oneline, email or raw, an additional line is inserted before the Author: line. This line begins with "Merge: " and the hashes of ancestral commits are printed, separated by spaces. Note that the listed commits may not necessarily be the list of the direct parent commits if you have limited your view of history: for example, if you are only interested in changes related to a certain directory or file.
There are several built-in formats, and you can define additional formats by setting a pretty.<name> config option to either another format name, or a format: string, as described below (see the section called “git-config(1)”). Here are the details of the built-in formats:
oneline
<hash> <title-line>
This is designed to be as compact as possible.
short
commit <hash> Author: <author>
<title-line>
medium
commit <hash> Author: <author> Date: <author-date>
<title-line>
<full-commit-message>
full
commit <hash> Author: <author> Commit: <committer>
<title-line>
<full-commit-message>
fuller
commit <hash> Author: <author> AuthorDate: <author-date> Commit: <committer> CommitDate: <committer-date>
<title-line>
<full-commit-message>
reference
<abbrev-hash> (<title-line>, <short-author-date>)
This format is used to refer to another commit in a commit message and is the same as --pretty='format:%C(auto)%h (%s, %ad)'. By default, the date is formatted with --date=short unless another --date option is explicitly specified. As with any format: with format placeholders, its output is not affected by other options like --decorate and --walk-reflogs.
From <hash> <date> From: <author> Date: <author-date> Subject: [PATCH] <title-line>
<full-commit-message>
mboxrd
Like email, but lines in the commit message starting with "From " (preceded by zero or more ">") are quoted with ">" so they aren't confused as starting a new commit.
raw
The raw format shows the entire commit exactly as stored in the commit object. Notably, the hashes are displayed in full, regardless of whether --abbrev or --no-abbrev are used, and parents information show the true parent commits, without taking grafts or history simplification into account. Note that this format affects the way commits are displayed, but not the way the diff is shown e.g. with git log --raw. To get full object names in a raw diff format, use --no-abbrev.
format:<format-string>
The format:<format-string> format allows you to specify which information you want to show. It works a little bit like printf format, with the notable exception that you get a newline with %n instead of \n.
E.g, format:"The author of %h was %an, %ar%nThe title was >>%s<<%n" would show something like this:
The author of fe6e0ee was Junio C Hamano, 23 hours ago The title was >>t4119: test autocomputing -p<n> for traditional diff input.<<
The placeholders are:
Placeholders that expand to a single literal character:
Placeholders that affect formatting of later placeholders:
Placeholders that expand to information extracted from the commit:
ref names with custom decorations. The decorate string may be followed by a colon and zero or more comma-separated options. Option values may contain literal formatting codes. These must be used for commas (%x2C) and closing parentheses (%x29), due to their role in the option syntax.
For example, to produce decorations with no wrapping or tag annotations, and spaces as separators:
%(decorate:prefix=,suffix=,tag=,separator= )
human-readable name, like the section called “git-describe(1)”; empty string for undescribable commits. The describe string may be followed by a colon and zero or more comma-separated options. Descriptions can be inconsistent when tags are added or removed at the same time.
display the trailers of the body as interpreted by the section called “git-interpret-trailers(1)”. The trailers string may be followed by a colon and zero or more comma-separated options. If any option is provided multiple times, the last occurrence wins.
Some placeholders may depend on other options given to the revision traversal engine. For example, the %g* reflog options will insert an empty string unless we are traversing reflog entries (e.g., by git log -g). The %d and %D placeholders will use the "short" decoration format if --decorate was not already provided on the command line.
The boolean options accept an optional value [=<bool-value>]. The values taken by --type=bool git-config[1], like yes and off, are all accepted. Giving a boolean option without =<value> is equivalent to giving it with =true.
If you add a + (plus sign) after % of a placeholder, a line-feed is inserted immediately before the expansion if and only if the placeholder expands to a non-empty string.
If you add a - (minus sign) after % of a placeholder, all consecutive line-feeds immediately preceding the expansion are deleted if and only if the placeholder expands to an empty string.
If you add a ` ` (space) after % of a placeholder, a space is inserted immediately before the expansion if and only if the placeholder expands to a non-empty string.
tformat:
The tformat: format works exactly like format:, except that it provides "terminator" semantics instead of "separator" semantics. In other words, each commit has the message terminator character (usually a newline) appended, rather than a separator placed between entries. This means that the final entry of a single-line format will be properly terminated with a new line, just as the "oneline" format does. For example:
$ git log -2 --pretty=format:%h 4da45bef \ | perl -pe '$_ .= " -- NO NEWLINE\n" unless /\n/' 4da45be 7134973 -- NO NEWLINE $ git log -2 --pretty=tformat:%h 4da45bef \ | perl -pe '$_ .= " -- NO NEWLINE\n" unless /\n/' 4da45be 7134973
In addition, any unrecognized string that has a % in it is interpreted as if it has tformat: in front of it. For example, these two are equivalent:
$ git log -2 --pretty=tformat:%h 4da45bef $ git log -2 --pretty=%h 4da45bef
Print the list of commits reachable from the current branch.
git rev-list HEAD
Print the list of commits on this branch, but not present in the upstream branch.
git rev-list @{upstream}..HEADFormat commits with their author and commit message (see also the porcelain the section called “git-log(1)”).
git rev-list --format=medium HEAD
Format commits along with their diffs (see also the porcelain the section called “git-log(1)”, which can do this in a single process).
git rev-list HEAD | git diff-tree --stdin --format=medium -p
Print the list of commits on the current branch that touched any file in the Documentation directory.
git rev-list HEAD -- Documentation/
Print the list of commits authored by you in the past year, on any branch, tag, or other ref.
git rev-list --author=you@example.com --since=1.year.ago --all
Print the list of objects reachable from the current branch (i.e., all commits and the blobs and trees they contain).
git rev-list --objects HEAD
Compare the disk size of all reachable objects, versus those reachable from reflogs, versus the total packed size. This can tell you whether running git repack -ad might reduce the repository size (by dropping unreachable objects), and whether expiring reflogs might help.
# reachable objects git rev-list --disk-usage --objects --all # plus reflogs git rev-list --disk-usage --objects --all --reflog # total disk size used du -c .git/objects/pack/*.pack .git/objects/??/* # alternative to du: add up "size" and "size-pack" fields git count-objects -v
Report the disk size of each branch, not including objects used by the current branch. This can find outliers that are contributing to a bloated repository size (e.g., because somebody accidentally committed large build artifacts).
git for-each-ref --format='%(refname)' |
while read branch
do
size=$(git rev-list --disk-usage --objects HEAD..$branch)
echo "$size $branch"
done |
sort -nCompare the on-disk size of branches in one group of refs, excluding another. If you co-mingle objects from multiple remotes in a single repository, this can show which remotes are contributing to the repository size (taking the size of origin as a baseline).
git rev-list --disk-usage --objects --remotes=$suspect --not --remotes=origin
Part of the the section called “git(1)” suite
Many Git porcelainish commands take a mixture of flags (i.e. parameters that begin with a dash -) and parameters meant for the underlying git rev-list command they use internally and flags and parameters for the other commands they use downstream of git rev-list. The primary purpose of this command is to allow calling programs to distinguish between them. There are a few other operation modes that have nothing to do with the above "help parse command line options".
Unless otherwise specified, most of the options and operation modes require you to run this command inside a git repository or a working tree that is under the control of a git repository, and will give you a fatal error otherwise.
Each of these options must appear first on the command line.
Behave as if git rev-parse was invoked from the <arg> subdirectory of the working tree. Any relative filenames are resolved as if they are prefixed by <arg> and will be printed in that form.
This can be used to convert arguments to a command run in a subdirectory so that they can still be used after moving to the top-level of the repository. For example:
prefix=$(git rev-parse --show-prefix) cd "$(git rev-parse --show-toplevel)" # rev-parse provides the -- needed for 'set' eval "set $(git rev-parse --sq --prefix "$prefix" -- "$@")"
Verify that exactly one parameter is provided, and that it can be turned into a raw 20-byte SHA-1 that can be used to access the object database. If so, emit it to the standard output; otherwise, error out.
If you want to make sure that the output actually names an object in your object database and/or can be used as a specific type of object you require, you can add the ^{type} peeling operator to the parameter. For example, git rev-parse "$VAR^{commit}" will make sure $VAR names an existing object that is a commit-ish (i.e. a commit, or an annotated tag that points at a commit). To make sure that $VAR names an existing object of any type, git rev-parse "$VAR^{object}" can be used.
Note that if you are verifying a name from an untrusted source, it is wise to use --end-of-options so that the name argument is not mistaken for another option.
Allow oids to be input from any object format that the current repository supports.
Specifying "sha1" translates if necessary and returns a sha1 oid.
Specifying "sha256" translates if necessary and returns a sha256 oid.
Specifying "storage" translates if necessary and returns an oid in encoded in the storage hash algorithm.
Show all branches, tags, or remote-tracking branches, respectively (i.e., refs found in refs/heads, refs/tags, or refs/remotes, respectively).
If a pattern is given, only refs matching the given shell glob are shown. If the pattern does not contain a globbing character (?, *, or [), it is turned into a prefix match by appending /*.
Do not include refs matching <glob-pattern> that the next --all, --branches, --tags, --remotes, or --glob would otherwise consider. Repetitions of this option accumulate exclusion patterns up to the next --all, --branches, --tags, --remotes, or --glob option (other options or arguments do not clear accumulated patterns).
The patterns given should not begin with refs/heads, refs/tags, or refs/remotes when applied to --branches, --tags, or --remotes, respectively, and they must begin with refs/ when applied to --glob or --all. If a trailing /* is intended, it must be given explicitly.
Controls the behavior of certain other options. If specified as absolute, the paths printed by those options will be absolute and canonical. If specified as relative, the paths will be relative to the current working directory if that is possible. The default is option specific.
This option may be specified multiple times and affects only the arguments that follow it on the command line, either to the end of the command line or the next instance of this option.
The following options are modified by --path-format:
Show $GIT_DIR if defined. Otherwise show the path to the .git directory. The path shown, when relative, is relative to the current working directory.
If $GIT_DIR is not defined and the current directory is not detected to lie in a Git repository or work tree print a message to stderr and exit with nonzero status.
The following options are unaffected by --path-format:
A revision parameter <rev> typically, but not necessarily, names a commit object. It uses what is called an extended SHA-1 syntax. Here are various ways to spell object names. The ones listed near the end of this list name trees and blobs contained in a commit.
This document shows the "raw" syntax as seen by git. The shell and other UIs might require additional quoting to protect special characters and to avoid word splitting.
A symbolic ref name. E.g. master typically means the commit object referenced by refs/heads/master. If you happen to have both heads/master and tags/master, you can explicitly say heads/master to tell Git which one you mean. When ambiguous, a <refname> is disambiguated by taking the first match in the following rules:
Note that any of the refs/* cases above may come either from the $GIT_DIR/refs directory or from the $GIT_DIR/packed-refs file. While the ref name encoding is unspecified, UTF-8 is preferred as some output processing may assume ref names in UTF-8.
The suffix @{push} reports the branch "where we would push to" if git push were run while branchname was checked out (or the current HEAD if no branchname is specified). Like for @{upstream}, we report the remote-tracking branch that corresponds to that branch at the remote.
Here's an example to make it more clear:
$ git config push.default current
$ git config remote.pushdefault myfork
$ git switch -c mybranch origin/master
$ git rev-parse --symbolic-full-name @{upstream}
refs/remotes/origin/master
$ git rev-parse --symbolic-full-name @{push}
refs/remotes/myfork/mybranchNote in the example that we set up a triangular workflow, where we pull from one location and push to another. In a non-triangular workflow, @{push} is the same as @{upstream}, and there is no need for it.
This suffix is also accepted when spelled in uppercase, and means the same thing no matter the case.
A suffix ^ followed by an object type name enclosed in brace pair means dereference the object at <rev> recursively until an object of type <type> is found or the object cannot be dereferenced anymore (in which case, barf). For example, if <rev> is a commit-ish, <rev>^{commit} describes the corresponding commit object. Similarly, if <rev> is a tree-ish, <rev>^{tree} describes the corresponding tree object. <rev>^0 is a short-hand for <rev>^{commit}.
<rev>^{object} can be used to make sure <rev> names an object that exists, without requiring <rev> to be a tag, and without dereferencing <rev>; because a tag is already an object, it does not have to be dereferenced even once to get to an object.
<rev>^{tag} can be used to ensure that <rev> identifies an existing tag object.
Here is an illustration, by Jon Loeliger. Both commit nodes B and C are parents of commit node A. Parent commits are ordered left-to-right.
G H I J
\ / \ /
D E F
\ | / \
\ | / |
\|/ |
B C
\ /
\ /
AA = = A^0 B = A^ = A^1 = A~1 C = = A^2 D = A^^ = A^1^1 = A~2 E = B^2 = A^^2 F = B^3 = A^^3 G = A^^^ = A^1^1^1 = A~3 H = D^2 = B^^2 = A^^^2 = A~2^2 I = F^ = B^3^ = A^^3^ J = F^2 = B^3^2 = A^^3^2
History traversing commands such as git log operate on a set of commits, not just a single commit.
For these commands, specifying a single revision, using the notation described in the previous section, means the set of commits reachable from the given commit.
Specifying several revisions means the set of commits reachable from any of the given commits.
A commit's reachable set is the commit itself and the commits in its ancestry chain.
There are several notations to specify a set of connected commits (called a "revision range"), illustrated below.
In these two shorthand notations, you can omit one end and let it default to HEAD. For example, origin.. is a shorthand for origin..HEAD and asks "What did I do since I forked from the origin branch?" Similarly, ..origin is a shorthand for HEAD..origin and asks "What did the origin do since I forked from them?" Note that .. would mean HEAD..HEAD which is an empty range that is both reachable and unreachable from HEAD.
Commands that are specifically designed to take two distinct ranges (e.g. "git range-diff R1 R2" to compare two ranges) do exist, but they are exceptions. Unless otherwise noted, all "git" commands that operate on a set of commits work on a single revision range. In other words, writing two "two-dot range notation" next to each other, e.g.
$ git log A..B C..D
does not specify two revision ranges for most commands. Instead it will name a single connected set of commits, i.e. those that are reachable from either B or D but are reachable from neither A or C. In a linear history like this:
---A---B---o---o---C---D
because A and B are reachable from C, the revision range specified by these two dotted ranges is a single commit D.
Three other shorthands exist, particularly useful for merge commits, for naming a set that is formed by a commit and its parent commits.
The r1^@ notation means all parents of r1.
The r1^! notation includes commit r1 but excludes all of its parents. By itself, this notation denotes the single commit r1.
The <rev>^-[<n>] notation includes <rev> but excludes the <n>th parent (i.e. a shorthand for <rev>^<n>..<rev>), with <n> = 1 if not given. This is typically useful for merge commits where you can just pass <commit>^- to get all the commits in the branch that was merged in merge commit <commit> (including <commit> itself).
While <rev>^<n> was about specifying a single commit parent, these three notations also consider its parents. For example you can say HEAD^2^@, however you cannot say HEAD^@^2.
Here are a handful of examples using the Loeliger illustration above, with each step in the notation's expansion and selection carefully spelt out:
Args Expanded arguments Selected commits
D G H D
D F G H I J D F
^G D H D
^D B E I J F B
^D B C E I J F B C
C I J F C
B..C = ^B C C
B...C = B ^F C G H D E B C
B^- = B^..B
= ^B^1 B E I J F B
C^@ = C^1
= F I J F
B^@ = B^1 B^2 B^3
= D E F D G H E F I J
C^! = C ^C^@
= C ^C^1
= C ^F C
B^! = B ^B^@
= B ^B^1 ^B^2 ^B^3
= B ^D ^E ^F B
F^! D = F ^I ^J D G H D FIn --parseopt mode, git rev-parse helps massaging options to bring to shell scripts the same facilities C builtins have. It works as an option normalizer (e.g. splits single switches aggregate values), a bit like getopt(1) does.
It takes on the standard input the specification of the options to parse and understand, and echoes on the standard output a string suitable for sh(1) eval to replace the arguments with normalized ones. In case of error, it outputs usage on the standard error stream, and exits with code 129.
Note: Make sure you quote the result when passing it to eval. See below for an example.
git rev-parse --parseopt input format is fully text based. It has two parts, separated by a line that contains only --. The lines before the separator (should be one or more) are used for the usage. The lines after the separator describe the options.
Each line of options has this format:
<opt-spec><flags>*<arg-hint>? SP+ help LF
<flags> are of *, =, ? or !.
The remainder of the line, after stripping the spaces, is used as the help associated with the option.
Blank lines are ignored, and lines that don't match this specification are used as option group headers (start the line with a space to create such lines on purpose).
OPTS_SPEC="\ some-command [<options>] <args>... some-command does foo and bar! -- h,help! show the help foo some nifty option --foo bar= some cool option --bar with an argument baz=arg another cool option --baz with a named argument qux?path qux may take a path argument but has meaning by itself An option group Header C? option C with an optional argument" eval "$(echo "$OPTS_SPEC" | git rev-parse --parseopt -- "$@" || echo exit $?)"
When "$@" is -h or --help in the above example, the following usage text would be shown:
usage: some-command [<options>] <args>...
some-command does foo and bar!
-h, --help show the help
--[no-]foo some nifty option --foo
--[no-]bar ... some cool option --bar with an argument
--[no-]baz <arg> another cool option --baz with a named argument
--[no-]qux[=<path>] qux may take a path argument but has meaning by itself
An option group Header
-C[...] option C with an optional argumentIn --sq-quote mode, git rev-parse echoes on the standard output a single line suitable for sh(1) eval. This line is made by normalizing the arguments following --sq-quote. Nothing other than quoting the arguments is done.
If you want command input to still be interpreted as usual by git rev-parse before the output is shell quoted, see the --sq option.
Print the object name of the current commit:
$ git rev-parse --verify HEAD
Print the commit object name from the revision in the $REV shell variable:
$ git rev-parse --verify --end-of-options $REV^{commit}This will error out if $REV is empty or not a valid revision.
Similar to above:
$ git rev-parse --default master --verify --end-of-options $REV
but if $REV is empty, the commit object name from master will be printed.
Part of the the section called “git(1)” suite
git revert [--[no-]edit] [-n] [-m <parent-number>] [-s] [-S[<keyid>]] <commit>…
git revert (--continue | --skip | --abort | --quit)
Given one or more existing commits, revert the changes that the related patches introduce, and record some new commits that record them. This requires your working tree to be clean (no modifications from the HEAD commit).
Note: git revert is used to record some new commits to reverse the effect of some earlier commits (often only a faulty one). If you want to throw away all uncommitted changes in your working directory, you should see the section called “git-reset(1)”, particularly the --hard option. If you want to extract specific files as they were in another commit, you should see the section called “git-restore(1)”, specifically the --source option. Take care with these alternatives as both will discard uncommitted changes in your working directory.
See "Reset, restore and revert" in the section called “git(1)” for the differences between the three commands.
Usually you cannot revert a merge because you do not know which side of the merge should be considered the mainline. This option specifies the parent number (starting from 1) of the mainline and allows revert to reverse the change relative to the specified parent.
Reverting a merge commit declares that you will never want the tree changes brought in by the merge. As a result, later merges will only bring in tree changes introduced by commits that are not ancestors of the previously reverted merge. This may or may not be what you want.
See the revert-a-faulty-merge How-To for more details.
Usually the command automatically creates some commits with commit log messages stating which commits were reverted. This flag applies the changes necessary to revert the named commits to your working tree and the index, but does not make the commits. In addition, when this option is used, your index does not have to match the HEAD commit. The revert is done against the beginning state of your index.
This is useful when reverting more than one commits' effect to your index in a row.
While git creates a basic commit message automatically, it is strongly recommended to explain why the original commit is being reverted. In addition, repeatedly reverting reverts will result in increasingly unwieldy subject lines, for example Reapply "Reapply "<original-subject>"". Please consider rewording these to be shorter and more unique.
Everything below this line in this section is selectively included from the the section called “git-config(1)” documentation. The content is the same as what's found there:
Part of the the section called “git(1)” suite
gitrm[-f|--force] [-n] [-r] [--cached] [--ignore-unmatch]
[--quiet] [--pathspec-from-file=<file> [--pathspec-file-nul]]
[--] [<pathspec>…]
Remove files matching pathspec from the index, or from the working tree and the index. git rm will not remove a file from just your working directory. (There is no option to remove a file only from the working tree and yet keep it in the index; use /bin/rm if you want to do that.) The files being removed have to be identical to the tip of the branch, and no updates to their contents can be staged in the index, though that default behavior can be overridden with the -f option. When --cached is given, the staged content has to match either the tip of the branch or the file on disk, allowing the file to be removed from just the index. When sparse-checkouts are in use (see the section called “git-sparse-checkout(1)”), git rm will only remove paths within the sparse-checkout patterns.
Files to remove. A leading directory name (e.g. dir to remove dir/file1 and dir/file2) can be given to remove all files in the directory, and recursively all sub-directories, but this requires the -r option to be explicitly given.
The command removes only the paths that are known to Git.
File globbing matches across directory boundaries. Thus, given two directories d and d2, there is a difference between using git rm 'd*' and git rm 'd/*', as the former will also remove all of directory d2.
For more details, see the <pathspec> entry in the section called “gitglossary(7)”.
There is no option for git rm to remove from the index only the paths that have disappeared from the filesystem. However, depending on the use case, there are several ways that can be done.
If you intend that your next commit should record all modifications of tracked files in the working tree and record all removals of files that have been removed from the working tree with rm (as opposed to git rm), use git commit -a, as it will automatically notice and record all removals. You can also have a similar effect without committing by using git add -u.
When accepting a new code drop for a vendor branch, you probably want to record both the removal of paths and additions of new paths as well as modifications of existing paths.
Typically you would first remove all tracked files from the working tree using this command:
git ls-files -z | xargs -0 rm -f
and then untar the new code in the working tree. Alternately you could rsync the changes into the working tree.
After that, the easiest way to record all removals, additions, and modifications in the working tree is:
git add -A
Only submodules using a gitfile (which means they were cloned with a Git version 1.7.8 or newer) will be removed from the work tree, as their repository lives inside the .git directory of the superproject. If a submodule (or one of those nested inside it) still uses a .git directory, git rm moves the submodules git directory into the superprojects git directory to protect the submodule's history. If it exists the submodule.<name> section in the the section called “gitmodules(5)” file will also be removed and that file will be staged (unless --cached or -n are used).
A submodule is considered up to date when the HEAD is the same as recorded in the index, no tracked files are modified and no untracked files that aren't ignored are present in the submodule's work tree. Ignored files are deemed expendable and won't stop a submodule's work tree from being removed.
If you only want to remove the local checkout of a submodule from your work tree without committing the removal, use the section called “git-submodule(1)” deinit instead. Also see the section called “gitsubmodules(7)” for details on submodule removal.
Removes all *.txt files from the index that are under the Documentation directory and any of its subdirectories.
Note that the asterisk * is quoted from the shell in this example; this lets Git, and not the shell, expand the pathnames of files and subdirectories under the Documentation/ directory.
Each time a superproject update removes a populated submodule (e.g. when switching between commits before and after the removal) a stale submodule checkout will remain in the old location. Removing the old directory is only safe when it uses a gitfile, as otherwise the history of the submodule will be deleted too. This step will be obsolete when recursive submodule update has been implemented.
Part of the the section called “git(1)” suite
git send-email [<options>] (<file>|<directory>)…
git send-email [<options>] <format-patch-options>
git send-email --dump-aliases
git send-email --translate-aliases
Takes the patches given on the command line and emails them out. Patches can be specified as files, directories (which will send all files in the directory), or directly as a revision list. In the last case, any format accepted by the section called “git-format-patch(1)” can be passed to git send-email, as well as options understood by the section called “git-format-patch(1)”.
The header of the email is configurable via command-line options. If not specified on the command line, the user will be prompted with a ReadLine enabled interface to provide the necessary information.
There are two formats accepted for patch files:
mbox format files
This is what the section called “git-format-patch(1)” generates. Most headers and MIME formatting are ignored.
The original format used by Greg Kroah-Hartman's send_lots_of_email.pl script
This format expects the first line of the file to contain the "Cc:" value and the "Subject:" of the message as the second line.
Specify a "Bcc:" value for each email. Default is the value of sendemail.bcc.
This option may be specified multiple times.
Specify a starting "Cc:" value for each email. Default is the value of sendemail.cc.
This option may be specified multiple times.
Invoke a text editor (see GIT_EDITOR in the section called “git-var(1)”) to edit an introductory message for the patch series.
When --compose is used, git send-email will use the From, To, Cc, Bcc, Subject, Reply-To, and In-Reply-To headers specified in the message. If the body of the message (what you type after the headers and a blank line) only contains blank (or Git: prefixed) lines, the summary won't be sent, but the headers mentioned above will be used unless they are removed.
Missing From or In-Reply-To headers will be prompted for.
See the CONFIGURATION section for sendemail.multiEdit.
Make the first mail (or all the mails with --no-thread) appear as a reply to the given Message-ID, which avoids breaking threads to provide a new patch series. The second and subsequent emails will be sent as replies according to the --[no-]chain-reply-to setting.
So for example when --thread and --no-chain-reply-to are specified, the second and subsequent patches will be replies to the first one like in the illustration below where [PATCH v2 0/3] is in reply to [PATCH 0/2]:
[PATCH 0/2] Here is what I did...
[PATCH 1/2] Clean up and tests
[PATCH 2/2] Implementation
[PATCH v2 0/3] Here is a reroll
[PATCH v2 1/3] Clean up
[PATCH v2 2/3] New tests
[PATCH v2 3/3] ImplementationOnly necessary if --compose is also set. If --compose is not set, this will be prompted for.
Microsoft Outlook SMTP servers discard the Message-ID sent via email and assign a new random Message-ID, thus breaking threads.
With --outlook-id-fix, git send-email uses a mechanism specific to Outlook servers to learn the Message-ID the server assigned to fix the threading. Use it only when you know that the server reports the rewritten Message-ID the same way as Outlook servers do.
Without this option specified, the fix is done by default when talking to smtp.office365.com or smtp-mail.outlook.com. Use --no-outlook-id-fix to disable even when talking to these two servers.
Specify the primary recipient of the emails generated. Generally, this will be the upstream maintainer of the project involved. Default is the value of the sendemail.to configuration value; if that is unspecified, and --to-cmd is not specified, this will be prompted for.
This option may be specified multiple times.
When encountering a non-ASCII message or subject that does not declare its encoding, add headers/quoting to indicate it is encoded in <encoding>. Default is the value of the sendemail.assume8bitEncoding; if that is unspecified, this will be prompted for if any non-ASCII files are encountered.
Note that no attempts whatsoever are made to validate the encoding.
Specify the transfer encoding to be used to send the message over SMTP. 7bit will fail upon encountering a non-ASCII message. quoted-printable can be useful when the repository contains files that contain carriage returns, but makes the raw patch email file (as saved from a MUA) much harder to inspect manually. base64 is even more fool proof, but also even more opaque. auto will use 8bit when possible, and quoted-printable otherwise.
Default is the value of the sendemail.transferEncoding configuration value; if that is unspecified, default to auto.
Whitespace-separated list of allowed SMTP-AUTH mechanisms. This setting forces using only the listed mechanisms. Example:
$ git send-email --smtp-auth="PLAIN LOGIN GSSAPI" ...
If at least one of the specified mechanisms matches the ones advertised by the SMTP server and if it is supported by the utilized SASL library, the mechanism is used for authentication. If neither sendemail.smtpAuth nor --smtp-auth is specified, all mechanisms supported by the SASL library can be used. The special value none maybe specified to completely disable authentication independently of --smtp-user
Password for SMTP-AUTH. The argument is optional: If no argument is specified, then the empty string is used as the password. Default is the value of sendemail.smtpPass, however --smtp-pass always overrides this value.
Furthermore, passwords need not be specified in configuration files or on the command line. If a username has been specified (with --smtp-user or a sendemail.smtpUser), but no password has been specified (with --smtp-pass or sendemail.smtpPass), then a password is obtained using git-credential.
If set, specifies the outgoing SMTP server to use (e.g. smtp.example.com or a raw IP address). If unspecified, and if --sendmail-cmd is also unspecified, the default is to search for sendmail in /usr/sbin, /usr/lib and $PATH if such a program is available, falling back to localhost otherwise.
For backward compatibility, this option can also specify a full pathname of a sendmail-like program instead; the program must support the -i option. This method does not support passing arguments or using plain command names. For those use cases, consider using --sendmail-cmd instead.
If set, specifies the outgoing SMTP server option to use. Default value can be specified by the sendemail.smtpServerOption configuration option.
The --smtp-server-option option must be repeated for each option you want to pass to the server. Likewise, different lines in the configuration files must be used for each option.
Specify an additional category of recipients to suppress the auto-cc of:
Default is the value of sendemail.suppressCc configuration value; if that is unspecified, default to self if --suppress-from is specified, as well as body if --no-signed-off-cc is specified.
If this is set, the In-Reply-To and References headers will be added to each email sent. Whether each mail refers to the previous email (deep threading per git format-patch wording) or to the first email (shallow threading) is governed by "--[no-]chain-reply-to".
If disabled with "--no-thread", those headers will not be added (unless specified with --in-reply-to). Default is the value of the sendemail.thread configuration value; if that is unspecified, default to --thread.
It is up to the user to ensure that no In-Reply-To header already exists when git send-email is asked to add it (especially note that git format-patch can be configured to do the threading itself). Failure to do so may not produce the expected result in the recipient's MUA.
Confirm just before sending:
Default is the value of sendemail.confirm configuration value; if that is unspecified, default to auto unless any of the suppress options have been specified, in which case default to compose.
Perform sanity checks on patches. Currently, validation means the following:
Default is the value of sendemail.validate; if this is not set, default to --validate.
Everything below this line in this section is selectively included from the the section called “git-config(1)” documentation. The content is the same as what's found there:
Format of the file(s) specified in sendemail.aliasesFile. Must be one of mutt, mailrc, pine, elm, gnus, or sendmail.
What an alias file in each format looks like can be found in the documentation of the email program of the same name. The differences and limitations from the standard formats are described below:
To use git send-email to send your patches through the Gmail SMTP server, edit ~/.gitconfig to specify your account settings:
[sendemail]
smtpEncryption = tls
smtpServer = smtp.gmail.com
smtpUser = yourname@gmail.com
smtpServerPort = 587If you have multi-factor authentication set up on your Gmail account, you can generate an app-specific password for use with git send-email. Visit https://security.google.com/settings/security/apppasswords to create it.
You can also use OAuth2.0 authentication with Gmail. OAUTHBEARER and XOAUTH2 are common methods used for this type of authentication. Gmail supports both of them. As an example, if you want to use OAUTHBEARER, edit your ~/.gitconfig file and add smtpAuth = OAUTHBEARER to your account settings:
[sendemail]
smtpEncryption = tls
smtpServer = smtp.gmail.com
smtpUser = yourname@gmail.com
smtpServerPort = 587
smtpAuth = OAUTHBEARERUnlike Gmail, Microsoft Outlook no longer supports app-specific passwords. Therefore, OAuth2.0 authentication must be used for Outlook. Also, it only supports XOAUTH2 authentication method.
Edit ~/.gitconfig to specify your account settings for Outlook and use its SMTP server with git send-email:
[sendemail]
smtpEncryption = tls
smtpServer = smtp.office365.com
smtpUser = yourname@outlook.com
smtpServerPort = 587
smtpAuth = XOAUTH2Once your commits are ready to be sent to the mailing list, run the following commands:
$ git format-patch --cover-letter -M origin/master -o outgoing/ $ edit outgoing/0000-* $ git send-email outgoing/*
The first time you run it, you will be prompted for your credentials. Enter the app-specific or your regular password as appropriate.
If you have a credential helper configured (see the section called “git-credential(1)”), the password will be saved in the credential store so you won't have to type it the next time.
If you are using OAuth2.0 authentication, you need to use an access token in place of a password when prompted. Various OAuth2.0 token generators are available online. Community maintained credential helpers for Gmail and Outlook are also available:
You can also see the section called “gitcredentials(7)” for more OAuth based authentication helpers.
Note: the following core Perl modules that may be installed with your distribution of Perl are required: MIME::Base64, MIME::QuotedPrint, Net::Domain and Net::SMTP. These additional Perl modules are also required: Authen::SASL and Mail::Address.
Part of the the section called “git(1)” suite
git send-pack [--mirror] [--dry-run] [--force]
[--receive-pack=<git-receive-pack>]
[--verbose] [--thin] [--atomic]
[--[no-]signed | --signed=(true|false|if-asked)]
[<host>:]<directory> (--all | <ref>…)
Usually you would want to use git push, which is a higher-level wrapper of this command, instead. See the section called “git-push(1)”.
Invokes git-receive-pack on a possibly remote repository, and updates it from the current repository, sending named refs.
Take the list of refs from stdin, one per line. If there are refs specified on the command line in addition to this option, then the refs from stdin are processed after those on the command line.
If --stateless-rpc is specified together with this option then the list of refs must be in packet format (pkt-line). Each ref must be in a separate packet, and the list must end with a flush packet.
There are three ways to specify which refs to update on the remote end.
With the --all flag, all refs that exist locally are transferred to the remote side. You cannot specify any <ref> if you use this flag.
Without --all and without any <ref>, the heads that exist both on the local side and on the remote side are updated.
When one or more <ref> are specified explicitly (whether on the command line or via --stdin), it can be either a single pattern, or a pair of such patterns separated by a colon ":" (this means that a ref name cannot have a colon in it). A single pattern <name> is just shorthand for <name>:<name>.
Each pattern pair consists of the source side (before the colon) and the destination side (after the colon). The ref to be pushed is determined by finding a match that matches the source side, and where it is pushed is determined by using the destination side. The rules used to match a ref are the same rules used by git rev-parse to resolve a symbolic ref name. See the section called “git-rev-parse(1)”.
If <dst> does not match any remote ref, either
Without --force, the <src> ref is stored at the remote only if <dst> does not exist, or <dst> is a proper subset (i.e. an ancestor) of <src>. This check, known as the "fast-forward check", is performed to avoid accidentally overwriting the remote ref and losing other people's commits from there.
With --force, the fast-forward check is disabled for all refs.
Optionally, a <ref> parameter can be prefixed with a plus + sign to disable the fast-forward check only on that ref.
Part of the the section called “git(1)” suite
eval_gettext () {
printf "%s" "$1" | (
export PATH $(git sh-i18n--envsubst --variables "$1");
git sh-i18n--envsubst "$1"
)
}
This is not a command the end user would want to run. Ever. This documentation is meant for people who are studying the plumbing scripts and/or are writing new ones.
git sh-i18n--envsubst is Git's stripped-down copy of the GNU envsubst(1) program that comes with the GNU gettext package. It's used internally by the section called “git-sh-i18n(1)” to interpolate the variables passed to the eval_gettext function.
No promises are made about the interface, or that this program won't disappear without warning in the next version of Git. Don't use it.
Part of the the section called “git(1)” suite
This is not a command the end user would want to run. Ever. This documentation is meant for people who are studying the Porcelain-ish scripts and/or are writing new ones.
The 'git sh-i18n scriptlet is designed to be sourced (using .) by Git's porcelain programs implemented in shell script. It provides wrappers for the GNU gettext and eval_gettext functions accessible through the gettext.sh script, and provides pass-through fallbacks on systems without GNU gettext.
Part of the the section called “git(1)” suite
This is not a command the end user would want to run. Ever. This documentation is meant for people who are studying the Porcelain-ish scripts and/or are writing new ones.
The git sh-setup scriptlet is designed to be sourced (using .) by other shell scripts to set up some variables pointing at the normal Git directories and a few helper shell functions.
Before sourcing it, your script should set up a few variables; USAGE (and LONG_USAGE, if any) is used to define the message given by usage() shell function. SUBDIRECTORY_OK can be set if the script can run from a subdirectory of the working tree (some commands do not).
The scriptlet sets GIT_DIR and GIT_OBJECT_DIRECTORY shell variables, but does not export them to the environment.
checks that the working tree and index associated with the repository have no uncommitted changes to tracked files. Otherwise it emits an error message of the form Cannot <action>: <reason>. <hint>, and dies. Example:
require_clean_work_tree rebase "Please commit or stash them."
Part of the the section called “git(1)” suite
chsh -s $(command -v git-shell) <user>
git clone <user>@localhost:/path/to/repo.git
ssh <user>@localhost
This is a login shell for SSH accounts to provide restricted Git access. It permits execution only of server-side Git commands implementing the pull/push functionality, plus custom commands present in a subdirectory named git-shell-commands in the user's home directory.
git shell accepts the following commands after the -c option:
If a ~/git-shell-commands directory is present, git shell will also handle other, custom commands by running "git-shell-commands/<command> <arguments>" from the user's home directory.
By default, the commands above can be executed only with the -c option; the shell is not interactive.
If a ~/git-shell-commands directory is present, git shell can also be run interactively (with no arguments). If a help command is present in the git-shell-commands directory, it is run to provide the user with an overview of allowed actions. Then a "git> " prompt is presented at which one can enter any of the commands from the git-shell-commands directory, or exit to close the connection.
Generally this mode is used as an administrative interface to allow users to list repositories they have access to, create, delete, or rename repositories, or change repository descriptions and permissions.
If a no-interactive-login command exists, then it is run and the interactive shell is aborted.
To disable interactive logins, displaying a greeting instead:
$ chsh -s /usr/bin/git-shell $ mkdir $HOME/git-shell-commands $ cat >$HOME/git-shell-commands/no-interactive-login <<\EOF #!/bin/sh printf '%s\n' "Hi $USER! You've successfully authenticated, but I do not" printf '%s\n' "provide interactive shell access." exit 128 EOF $ chmod +x $HOME/git-shell-commands/no-interactive-login
To enable git-cvsserver access (which should generally have the no-interactive-login example above as a prerequisite, as creating the git-shell-commands directory allows interactive logins):
$ cat >$HOME/git-shell-commands/cvs <<\EOF
if ! test $# = 1 && test "$1" = "server"
then
echo >&2 "git-cvsserver only handles \"server\""
exit 1
fi
exec git cvsserver server
EOF
$ chmod +x $HOME/git-shell-commands/cvsssh(1), the section called “git-daemon(1)”, contrib/git-shell-commands/README
Part of the the section called “git(1)” suite
git shortlog [<options>] [<revision-range>] [[--] <path>…]
git log --pretty=short | git shortlog [<options>]
Summarizes git log output in a format suitable for inclusion in release announcements. Each commit will be grouped by author and title.
Additionally, "[PATCH]" will be stripped from the commit description.
If no revisions are passed on the command line and either standard input is not a terminal or there is no current branch, git shortlog will output a summary of the log read from standard input, without reference to the current repository.
Instead of the commit subject, use some other information to describe each commit. <format> can be any string accepted by the --format option of git log, such as * [%h] %s. (See the "PRETTY FORMATS" section of the section called “git-log(1)”.)
Each pretty-printed commit will be rewrapped before it is shown.
Group commits based on <type>. If no --group option is specified, the default is author. <type> is one of:
format:<format>, any string accepted by the --format option of git log. (See the "PRETTY FORMATS" section of the section called “git-log(1)”.)
Note that commits that do not include the trailer will not be counted. Likewise, commits with multiple trailers (e.g., multiple signoffs) may be counted more than once (but only once per unique trailer value in that commit).
Shortlog will attempt to parse each trailer value as a name <email> identity. If successful, the mailmap is applied and the email is omitted unless the --email option is specified. If the value cannot be parsed as an identity, it will be taken literally and completely.
If --group is specified multiple times, commits are counted under each value (but again, only once per unique value in that commit). For example, git shortlog --group=author --group=trailer:co-authored-by counts both authors and co-authors.
Linewrap the output by wrapping each line at width. The first line of each entry is indented by indent1 spaces, and the second and subsequent lines are indented by indent2 spaces. width, indent1, and indent2 default to 76, 6 and 9 respectively.
If width is 0 (zero) then indent the lines of the output without wrapping them.
Consider only commits that are enough to explain how the files that match the specified paths came to be.
Paths may need to be prefixed with -- to separate them from options or the revision range, when confusion arises.
Besides specifying a range of commits that should be listed using the special notations explained in the description, additional commit limiting may be applied.
Using more options generally further limits the output (e.g. --since=<date1> limits to commits newer than <date1>, and using it with --grep=<pattern> further limits to commits whose log message has a line that matches <pattern>), unless otherwise noted.
Note that these are applied before commit ordering and formatting options, such as --reverse.
Limit the commits output to ones with a log message that matches the specified pattern (regular expression). With more than one --grep=<pattern>, commits whose message matches any of the given patterns are chosen (but see --all-match).
When --notes is in effect, the message from the notes is matched as if it were part of the log message.
Consider the limiting patterns to be Perl-compatible regular expressions.
Support for these types of regular expressions is an optional compile-time dependency. If Git wasn't compiled with support for them providing this option will cause it to die.
Show only commits which have at least (or at most) that many parent commits. In particular, --max-parents=1 is the same as --no-merges, --min-parents=2 is the same as --merges. --max-parents=0 gives all root commits and --min-parents=3 all octopus merges.
--no-min-parents and --no-max-parents reset these limits (to no limit) again. Equivalent forms are --min-parents=0 (any commit has 0 or more parents) and --max-parents=-1 (negative numbers denote no upper limit).
Do not include refs matching <glob-pattern> that the next --all, --branches, --tags, --remotes, or --glob would otherwise consider. Repetitions of this option accumulate exclusion patterns up to the next --all, --branches, --tags, --remotes, or --glob option (other options or arguments do not clear accumulated patterns).
The patterns given should not begin with refs/heads, refs/tags, or refs/remotes when applied to --branches, --tags, or --remotes, respectively, and they must begin with refs/ when applied to --glob or --all. If a trailing /* is intended, it must be given explicitly.
Omit any commit that introduces the same change as another commit on the other side when the set of commits are limited with symmetric difference.
For example, if you have two branches, A and B, a usual way to list all commits on only one side of them is with --left-right (see the example below in the description of the --left-right option). However, it shows the commits that were cherry-picked from the other branch (for example, 3rd on b may be cherry-picked from branch A). With this option, such pairs of commits are excluded from the output.
List only commits on the respective side of a symmetric difference, i.e. only those which would be marked < resp. > by --left-right.
For example, --cherry-pick --right-only A...B omits those commits from B which are in A or are patch-equivalent to a commit in A. In other words, this lists the + commits from git cherry A B. More precisely, --cherry-pick --right-only --no-merges gives the exact list.
Instead of walking the commit ancestry chain, walk reflog entries from the most recent one to older ones. When this option is used you cannot specify commits to exclude (that is, ^commit, commit1..commit2, and commit1...commit2 notations cannot be used).
With --pretty format other than oneline and reference (for obvious reasons), this causes the output to have two extra lines of information taken from the reflog. The reflog designator in the output may be shown as ref@{<Nth>} (where <Nth> is the reverse-chronological index in the reflog) or as ref@{<timestamp>} (with the <timestamp> for that entry), depending on a few rules:
Under --pretty=oneline, the commit message is prefixed with this information on the same line. This option cannot be combined with --reverse. See also the section called “git-reflog(1)”.
Under --pretty=reference, this information will not be shown at all.
Sometimes you are only interested in parts of the history, for example the commits modifying a particular <path>. But there are two parts of History Simplification, one part is selecting the commits and the other is how to do it, as there are various strategies to simplify the history.
The following options select the commits to be shown:
Note that extra commits can be shown to give a meaningful history.
The following options affect the way the simplification is performed:
A more detailed explanation follows.
Suppose you specified foo as the <paths>. We shall call commits that modify foo !TREESAME, and the rest TREESAME. (In a diff filtered for foo, they look different and equal, respectively.)
In the following, we will always refer to the same example history to illustrate the differences between simplification settings. We assume that you are filtering for a file foo in this commit graph:
.-A---M---N---O---P---Q
/ / / / / /
I B C D E Y
\ / / / / /
`-------------' XThe horizontal line of history A---Q is taken to be the first parent of each merge. The commits are:
rev-list walks backwards through history, including or excluding commits based on whether --full-history and/or parent rewriting (via --parents or --children) are used. The following settings are available.
Commits are included if they are not TREESAME to any parent (though this can be changed, see --sparse below). If the commit was a merge, and it was TREESAME to one parent, follow only that parent. (Even if there are several TREESAME parents, follow only one of them.) Otherwise, follow all parents.
This results in:
.-A---N---O
/ / /
I---------DNote how the rule to only follow the TREESAME parent, if one is available, removed B from consideration entirely. C was considered via N, but is TREESAME. Root commits are compared to an empty tree, so I is !TREESAME.
Parent/child relations are only visible with --parents, but that does not affect the commits selected in default mode, so we have shown the parent lines.
This mode differs from the default in one point: always follow all parents of a merge, even if it is TREESAME to one of them. Even if more than one side of the merge has commits that are included, this does not imply that the merge itself is! In the example, we get
I A B N D O P Q
M was excluded because it is TREESAME to both parents. E, C and B were all walked, but only B was !TREESAME, so the others do not appear.
Note that without parent rewriting, it is not really possible to talk about the parent/child relationships between the commits, so we show them disconnected.
Ordinary commits are only included if they are !TREESAME (though this can be changed, see --sparse below).
Merges are always included. However, their parent list is rewritten: Along each parent, prune away commits that are not included themselves. This results in
.-A---M---N---O---P---Q
/ / / / /
I B / D /
\ / / / /
`-------------'Compare to --full-history without rewriting above. Note that E was pruned away because it is TREESAME, but the parent list of P was rewritten to contain E's parent I. The same happened for C and N, and X, Y and Q.
In addition to the above settings, you can change whether TREESAME affects inclusion:
All commits that are walked are included.
Note that without --full-history, this still simplifies merges: if one of the parents is TREESAME, we follow only that one, so the other sides of the merge are never walked.
First, build a history graph in the same way that --full-history with parent rewriting does (see above).
Then simplify each commit C to its replacement C' in the final history according to the following rules:
The effect of this is best shown by way of comparing to --full-history with parent rewriting. The example turns into:
.-A---M---N---O
/ / /
I B D
\ / /
`---------'Note the major differences in N, P, and Q over --full-history:
There is another simplification mode available:
Limit the displayed commits to those which are an ancestor of <commit>, or which are a descendant of <commit>, or are <commit> itself.
As an example use case, consider the following commit history:
D---E-------F
/ \ \
B---C---G---H---I---J
/ \
A-------K---------------L--MA regular D..M computes the set of commits that are ancestors of M, but excludes the ones that are ancestors of D. This is useful to see what happened to the history leading to M since D, in the sense that what does M have that did not exist in D. The result in this example would be all the commits, except A and B (and D itself, of course).
When we want to find out what commits in M are contaminated with the bug introduced by D and need fixing, however, we might want to view only the subset of D..M that are actually descendants of D, i.e. excluding C and K. This is exactly what the --ancestry-path option does. Applied to the D..M range, it results in:
E-------F
\ \
G---H---I---J
\
L--MWe can also use --ancestry-path=D instead of --ancestry-path which means the same thing when applied to the D..M range but is just more explicit.
If we instead are interested in a given topic within this range, and all commits affected by that topic, we may only want to view the subset of D..M which contain that topic in their ancestry path. So, using --ancestry-path=H D..M for example would result in:
E
\
C---G---H---I---J
\
L--MWhereas --ancestry-path=K D..M would result in
K---------------L--M
Before discussing another option, --show-pulls, we need to create a new example history.
A common problem users face when looking at simplified history is that a commit they know changed a file somehow does not appear in the file's simplified history. Let's demonstrate a new example and show how options such as --full-history and --simplify-merges works in that case:
.-A---M-----C--N---O---P
/ / \ \ \/ / /
I B \ R-'`-Z' /
\ / \/ /
\ / /\ /
`---X--' `---Y--'For this example, suppose I created file.txt which was modified by A, B, and X in different ways. The single-parent commits C, Z, and Y do not change file.txt. The merge commit M was created by resolving the merge conflict to include both changes from A and B and hence is not TREESAME to either. The merge commit R, however, was created by ignoring the contents of file.txt at M and taking only the contents of file.txt at X. Hence, R is TREESAME to X but not M. Finally, the natural merge resolution to create N is to take the contents of file.txt at R, so N is TREESAME to R but not C. The merge commits O and P are TREESAME to their first parents, but not to their second parents, Z and Y respectively.
When using the default mode, N and R both have a TREESAME parent, so those edges are walked and the others are ignored. The resulting history graph is:
I---X
When using --full-history, Git walks every edge. This will discover the commits A and B and the merge M, but also will reveal the merge commits O and P. With parent rewriting, the resulting graph is:
.-A---M--------N---O---P
/ / \ \ \/ / /
I B \ R-'`--' /
\ / \/ /
\ / /\ /
`---X--' `------'Here, the merge commits O and P contribute extra noise, as they did not actually contribute a change to file.txt. They only merged a topic that was based on an older version of file.txt. This is a common issue in repositories using a workflow where many contributors work in parallel and merge their topic branches along a single trunk: many unrelated merges appear in the --full-history results.
When using the --simplify-merges option, the commits O and P disappear from the results. This is because the rewritten second parents of O and P are reachable from their first parents. Those edges are removed and then the commits look like single-parent commits that are TREESAME to their parent. This also happens to the commit N, resulting in a history view as follows:
.-A---M--.
/ / \
I B R
\ / /
\ / /
`---X--'In this view, we see all of the important single-parent changes from A, B, and X. We also see the carefully-resolved merge M and the not-so-carefully-resolved merge R. This is usually enough information to determine why the commits A and B "disappeared" from history in the default view. However, there are a few issues with this approach.
The first issue is performance. Unlike any previous option, the --simplify-merges option requires walking the entire commit history before returning a single result. This can make the option difficult to use for very large repositories.
The second issue is one of auditing. When many contributors are working on the same repository, it is important which merge commits introduced a change into an important branch. The problematic merge R above is not likely to be the merge commit that was used to merge into an important branch. Instead, the merge N was used to merge R and X into the important branch. This commit may have information about why the change X came to override the changes from A and B in its commit message.
In addition to the commits shown in the default history, show each merge commit that is not TREESAME to its first parent but is TREESAME to a later parent.
When a merge commit is included by --show-pulls, the merge is treated as if it "pulled" the change from another branch. When using --show-pulls on this example (and no other options) the resulting graph is:
I---X---R---N
Here, the merge commits R and N are included because they pulled the commits X and R into the base branch, respectively. These merges are the reason the commits A and B do not appear in the default history.
When --show-pulls is paired with --simplify-merges, the graph includes all of the necessary information:
.-A---M--. N
/ / \ /
I B R
\ / /
\ / /
`---X--'Notice that since M is reachable from R, the edge from N to M was simplified away. However, N still appears in the history as an important commit because it "pulled" the change R into the main branch.
The --simplify-by-decoration option allows you to view only the big picture of the topology of the history, by omitting commits that are not referenced by tags. Commits are marked as !TREESAME (in other words, kept after history simplification rules described above) if (1) they are referenced by tags, or (2) they change the contents of the paths given on the command line. All other commits are marked as TREESAME (subject to be simplified away).
See the section called “gitmailmap(5)”.
Note that if git shortlog is run outside of a repository (to process log contents on standard input), it will look for a .mailmap file in the current directory.
Part of the the section called “git(1)” suite
git show-branch [-a | --all] [-r | --remotes] [--topo-order | --date-order]
[--current] [--color[=<when>] | --no-color] [--sparse]
[--more=<n> | --list | --independent | --merge-base]
[--no-name | --sha1-name] [--topics]
[(<rev> | <glob>)…]
git show-branch (-g | --reflog)[=<n>[,<base>]] [--list] [<ref>]
Shows the commit ancestry graph starting from the commits named with <rev>s or <glob>s (or all refs under refs/heads and/or refs/tags) semi-visually.
It cannot show more than 26 branches and commits at a time.
It uses showbranch.default multi-valued configuration items if no <rev> or <glob> is given on the command line.
Note that --more, --list, --independent, and --merge-base options are mutually exclusive.
Given N <ref>s, the first N lines are the one-line description from their commit message. The branch head that is pointed at by $GIT_DIR/HEAD is prefixed with an asterisk * character while other heads are prefixed with a ! character.
Following these N lines, a one-line log for each commit is displayed, indented N places. If a commit is on the I-th branch, the I-th indentation character shows a + sign; otherwise it shows a space. Merge commits are denoted by a - sign. Each commit shows a short name that can be used as an extended SHA-1 to name that commit.
The following example shows three branches, "master", "fixes", and "mhf":
$ git show-branch master fixes mhf * [master] Add 'git show-branch'. ! [fixes] Introduce "reset type" flag to "git reset" ! [mhf] Allow "+remote:local" refspec to cause --force when fetching. --- + [mhf] Allow "+remote:local" refspec to cause --force when fetching. + [mhf~1] Use git-octopus when pulling more than one head. + [fixes] Introduce "reset type" flag to "git reset" + [mhf~2] "git fetch --force". + [mhf~3] Use .git/remote/origin, not .git/branches/origin. + [mhf~4] Make "git pull" and "git fetch" default to origin + [mhf~5] Infamous 'octopus merge' + [mhf~6] Retire git-parse-remote. + [mhf~7] Multi-head fetch. + [mhf~8] Start adding the $GIT_DIR/remotes/ support. *++ [master] Add 'git show-branch'.
These three branches all forked from a common commit, [master], whose commit message is "Add 'git show-branch'". The "fixes" branch adds one commit "Introduce "reset type" flag to "git reset"". The "mhf" branch adds many other commits. The current branch is "master".
If you keep your primary branches immediately under refs/heads, and topic branches in subdirectories of it, having the following in the configuration file may help:
[showbranch]
default = --topo-order
default = heads/*With this, git show-branch without extra parameters would show only the primary branches. In addition, if you happen to be on your topic branch, it is shown as well.
$ git show-branch --reflog="10,1 hour ago" --list master
shows 10 reflog entries going back from the tip as of 1 hour ago. Without --list, the output also shows how these tips are topologically related to each other.
Everything below this line in this section is selectively included from the the section called “git-config(1)” documentation. The content is the same as what's found there:
Part of the the section called “git(1)” suite
Read the .idx file for a Git packfile (created with the section called “git-pack-objects(1)” or the section called “git-index-pack(1)”) from the standard input, and dump its contents. The output consists of one object per line, with each line containing two or three space-separated columns:
The objects are output in the order in which they are found in the index file, which should be (in a correctly constructed file) sorted by object id.
Note that you can get more information on a packfile by calling the section called “git-verify-pack(1)”. However, as this command considers only the index file itself, it's both faster and more flexible.
Specify the given object format (hash algorithm) for the index file. The valid values are sha1 and (if enabled) sha256. The default is the algorithm for the current repository (set by extensions.objectFormat), or sha1 if no value is set or outside a repository..
Note: At present, there is no interoperability between SHA-256 repositories and SHA-1 repositories.
Historically, we warned that SHA-256 repositories may later need backward incompatible changes when we introduce such interoperability features. Today, we only expect compatible changes. Furthermore, if such changes prove to be necessary, it can be expected that SHA-256 repositories created with today's Git will be usable by future versions of Git without data loss.
Part of the the section called “git(1)” suite
git show-ref [--head] [-d | --dereference]
[-s | --hash[=<n>]] [--abbrev[=<n>]] [--branches] [--tags]
[--] [<pattern>…]
git show-ref --verify [-q | --quiet] [-d | --dereference]
[-s | --hash[=<n>]] [--abbrev[=<n>]]
[--] [<ref>…]
git show-ref --exclude-existing[=<pattern>]
git show-ref --exists <ref>
Displays references available in a local repository along with the associated commit IDs. Results can be filtered using a pattern and tags can be dereferenced into object IDs. Additionally, it can be used to test whether a particular ref exists.
By default, shows the tags, heads, and remote refs.
The --exclude-existing form is a filter that does the inverse. It reads refs from stdin, one ref per line, and shows those that don't exist in the local repository.
The --exists form can be used to check for the existence of a single references. This form does not verify whether the reference resolves to an actual object.
Use of this utility is encouraged in favor of directly accessing files under the .git directory.
The output is in the format:
<oid> SP <ref> LF
For example,
$ git show-ref --head --dereference
832e76a9899f560a90ffd62ae2ce83bbeff58f54 HEAD
832e76a9899f560a90ffd62ae2ce83bbeff58f54 refs/heads/master
832e76a9899f560a90ffd62ae2ce83bbeff58f54 refs/heads/origin
3521017556c5de4159da4615a39fa4d5d2c279b5 refs/tags/v0.99.9c
6ddc0964034342519a87fe013781abf31c6db6ad refs/tags/v0.99.9c^{}
055e4ae3ae6eb344cbabf2a5256a49ea66040131 refs/tags/v1.0rc4
423325a2d24638ddcc82ce47be5e40be550f4507 refs/tags/v1.0rc4^{}
...When using --hash (and not --dereference), the output is in the format:
<oid> LF
For example,
$ git show-ref --branches --hash 2e3ba0114a1f52b47df29743d6915d056be13278 185008ae97960c8d551adcd9e23565194651b5d1 03adf42c988195b50e1a1935ba5fcbc39b2b029b ...
To show all references called "master", whether tags or heads or anything else, and regardless of how deep in the reference naming hierarchy they are, use:
git show-ref master
This will show "refs/heads/master" but also "refs/remote/other-repo/master", if such references exist.
When using the --verify flag, the command requires an exact path:
git show-ref --verify refs/heads/master
will only match the exact branch called "master".
If nothing matches, git show-ref will return an error code of 1, and in the case of verification, it will show an error message.
For scripting, you can ask it to be quiet with the --quiet flag, which allows you to do things like
git show-ref --quiet --verify -- "refs/heads/$headname" ||
echo "$headname is not a valid branch"to check whether a particular branch exists or not (notice how we don't actually want to show any results, and we want to use the full refname for it in order to not trigger the problem with ambiguous partial matches).
To show only tags, or only proper branch heads, use --tags and/or --branches respectively (using both means that it shows tags and branches, but not other random references under the refs/ subdirectory).
To do automatic tag object dereferencing, use the -d or --dereference flag, so you can do
git show-ref --tags --dereference
to get a listing of all tags together with what they dereference.
the section called “git-for-each-ref(1)”, the section called “git-ls-remote(1)”, the section called “git-update-ref(1)”, the section called “gitrepository-layout(5)”
Part of the the section called “git(1)” suite
Shows one or more objects (blobs, trees, tags and commits).
For commits it shows the log message and textual diff. It also presents the merge commit in a special format as produced by git diff-tree --cc.
For tags, it shows the tag message and the referenced objects.
For trees, it shows the names (equivalent to git ls-tree with --name-only).
For plain blobs, it shows the plain contents.
Some options that git log command understands can be used to control how the changes the commit introduces are shown.
This manual page describes only the most frequently used options.
Pretty-print the contents of the commit logs in a given format, where <format> can be one of oneline, short, medium, full, fuller, reference, email, raw, format:<string> and tformat:<string>. When <format> is none of the above, and has %placeholder in it, it acts as if --pretty=tformat:<format> were given.
See the "PRETTY FORMATS" section for some additional details for each format. When =<format> part is omitted, it defaults to medium.
Note: you can specify the default pretty format in the repository configuration (see the section called “git-config(1)”).
Instead of showing the full 40-byte hexadecimal commit object name, show a prefix that names the object uniquely. "--abbrev=<n>" (which also modifies diff output, if it is displayed) option can be used to specify the minimum length of the prefix.
This should make "--pretty=oneline" a whole lot more readable for people using 80-column terminals.
Perform a tab expansion (replace each tab with enough spaces to fill to the next display column that is a multiple of <n>) in the log message before showing it in the output. --expand-tabs is a short-hand for --expand-tabs=8, and --no-expand-tabs is a short-hand for --expand-tabs=0, which disables tab expansion.
By default, tabs are expanded in pretty formats that indent the log message by 4 spaces (i.e. medium, which is the default, full, and fuller).
Show the notes (see the section called “git-notes(1)”) that annotate the commit, when showing the commit log message. This is the default for git log, git show and git whatchanged commands when there is no --pretty, --format, or --oneline option given on the command line.
By default, the notes shown are from the notes refs listed in the core.notesRef and notes.displayRef variables (or corresponding environment overrides). See the section called “git-config(1)” for more details.
With an optional <ref> argument, use the ref to find the notes to display. The ref can specify the full refname when it begins with refs/notes/; when it begins with notes/, refs/ and otherwise refs/notes/ is prefixed to form the full name of the ref.
Multiple --notes options can be combined to control which notes are being displayed. Examples: "--notes=foo" will show only notes from "refs/notes/foo"; "--notes=foo --notes" will show both notes from "refs/notes/foo" and from the default notes ref(s).
If the commit is a merge, and if the pretty-format is not oneline, email or raw, an additional line is inserted before the Author: line. This line begins with "Merge: " and the hashes of ancestral commits are printed, separated by spaces. Note that the listed commits may not necessarily be the list of the direct parent commits if you have limited your view of history: for example, if you are only interested in changes related to a certain directory or file.
There are several built-in formats, and you can define additional formats by setting a pretty.<name> config option to either another format name, or a format: string, as described below (see the section called “git-config(1)”). Here are the details of the built-in formats:
oneline
<hash> <title-line>
This is designed to be as compact as possible.
short
commit <hash> Author: <author>
<title-line>
medium
commit <hash> Author: <author> Date: <author-date>
<title-line>
<full-commit-message>
full
commit <hash> Author: <author> Commit: <committer>
<title-line>
<full-commit-message>
fuller
commit <hash> Author: <author> AuthorDate: <author-date> Commit: <committer> CommitDate: <committer-date>
<title-line>
<full-commit-message>
reference
<abbrev-hash> (<title-line>, <short-author-date>)
This format is used to refer to another commit in a commit message and is the same as --pretty='format:%C(auto)%h (%s, %ad)'. By default, the date is formatted with --date=short unless another --date option is explicitly specified. As with any format: with format placeholders, its output is not affected by other options like --decorate and --walk-reflogs.
From <hash> <date> From: <author> Date: <author-date> Subject: [PATCH] <title-line>
<full-commit-message>
mboxrd
Like email, but lines in the commit message starting with "From " (preceded by zero or more ">") are quoted with ">" so they aren't confused as starting a new commit.
raw
The raw format shows the entire commit exactly as stored in the commit object. Notably, the hashes are displayed in full, regardless of whether --abbrev or --no-abbrev are used, and parents information show the true parent commits, without taking grafts or history simplification into account. Note that this format affects the way commits are displayed, but not the way the diff is shown e.g. with git log --raw. To get full object names in a raw diff format, use --no-abbrev.
format:<format-string>
The format:<format-string> format allows you to specify which information you want to show. It works a little bit like printf format, with the notable exception that you get a newline with %n instead of \n.
E.g, format:"The author of %h was %an, %ar%nThe title was >>%s<<%n" would show something like this:
The author of fe6e0ee was Junio C Hamano, 23 hours ago The title was >>t4119: test autocomputing -p<n> for traditional diff input.<<
The placeholders are:
Placeholders that expand to a single literal character:
Placeholders that affect formatting of later placeholders:
Placeholders that expand to information extracted from the commit:
ref names with custom decorations. The decorate string may be followed by a colon and zero or more comma-separated options. Option values may contain literal formatting codes. These must be used for commas (%x2C) and closing parentheses (%x29), due to their role in the option syntax.
For example, to produce decorations with no wrapping or tag annotations, and spaces as separators:
%(decorate:prefix=,suffix=,tag=,separator= )
human-readable name, like the section called “git-describe(1)”; empty string for undescribable commits. The describe string may be followed by a colon and zero or more comma-separated options. Descriptions can be inconsistent when tags are added or removed at the same time.
display the trailers of the body as interpreted by the section called “git-interpret-trailers(1)”. The trailers string may be followed by a colon and zero or more comma-separated options. If any option is provided multiple times, the last occurrence wins.
Some placeholders may depend on other options given to the revision traversal engine. For example, the %g* reflog options will insert an empty string unless we are traversing reflog entries (e.g., by git log -g). The %d and %D placeholders will use the "short" decoration format if --decorate was not already provided on the command line.
The boolean options accept an optional value [=<bool-value>]. The values taken by --type=bool git-config[1], like yes and off, are all accepted. Giving a boolean option without =<value> is equivalent to giving it with =true.
If you add a + (plus sign) after % of a placeholder, a line-feed is inserted immediately before the expansion if and only if the placeholder expands to a non-empty string.
If you add a - (minus sign) after % of a placeholder, all consecutive line-feeds immediately preceding the expansion are deleted if and only if the placeholder expands to an empty string.
If you add a ` ` (space) after % of a placeholder, a space is inserted immediately before the expansion if and only if the placeholder expands to a non-empty string.
tformat:
The tformat: format works exactly like format:, except that it provides "terminator" semantics instead of "separator" semantics. In other words, each commit has the message terminator character (usually a newline) appended, rather than a separator placed between entries. This means that the final entry of a single-line format will be properly terminated with a new line, just as the "oneline" format does. For example:
$ git log -2 --pretty=format:%h 4da45bef \ | perl -pe '$_ .= " -- NO NEWLINE\n" unless /\n/' 4da45be 7134973 -- NO NEWLINE $ git log -2 --pretty=tformat:%h 4da45bef \ | perl -pe '$_ .= " -- NO NEWLINE\n" unless /\n/' 4da45be 7134973
In addition, any unrecognized string that has a % in it is interpreted as if it has tformat: in front of it. For example, these two are equivalent:
$ git log -2 --pretty=tformat:%h 4da45bef $ git log -2 --pretty=%h 4da45bef
The options below can be used to change the way git show generates diff output.
Specify diff format to be used for merge commits. Default is dense-combined unless --first-parent is in use, in which case first-parent is the default.
The following formats are supported:
Remerge two-parent merge commits to create a temporary tree object--potentially containing files with conflict markers and such. A diff is then shown between that temporary tree and the actual merge commit.
The output emitted when this option is used is subject to change, and so is its interaction with other options (unless explicitly documented).
Generate a diff using the "anchored diff" algorithm.
This option may be specified more than once.
If a line exists in both the source and destination, exists only once, and starts with <text>, this algorithm attempts to prevent it from appearing as a deletion or addition in the output. It uses the "patience diff" algorithm internally.
Choose a diff algorithm. The variants are as follows:
For instance, if you configured the diff.algorithm variable to a non-default value and want to use the default one, then you have to use --diff-algorithm=default option.
Generate a diffstat. By default, as much space as necessary will be used for the filename part, and the rest for the graph part. Maximum width defaults to terminal width, or 80 columns if not connected to a terminal, and can be overridden by <width>. The width of the filename part can be limited by giving another width <name-width> after a comma or by setting diff.statNameWidth=<name-width>. The width of the graph part can be limited by using --stat-graph-width=<graph-width> or by setting diff.statGraphWidth=<graph-width>. Using --stat or --stat-graph-width affects all commands generating a stat graph, while setting diff.statNameWidth or diff.statGraphWidth does not affect git format-patch. By giving a third parameter <count>, you can limit the output to the first <count> lines, followed by ... if there are more.
These parameters can also be set individually with --stat-width=<width>, --stat-name-width=<name-width> and --stat-count=<count>.
Output the distribution of relative amount of changes for each sub-directory. The behavior of --dirstat can be customized by passing it a comma separated list of parameters. The defaults are controlled by the diff.dirstat configuration variable (see the section called “git-config(1)”). The following parameters are available:
Example: The following will count changed files, while ignoring directories with less than 10% of the total amount of changed files, and accumulating child directory counts in the parent directories: --dirstat=files,10,cumulative.
Separate the commits with NULs instead of newlines.
Also, when --raw or --numstat has been given, do not munge pathnames and use NULs as output field terminators.
Without this option, pathnames with "unusual" characters are quoted as explained for the configuration variable core.quotePath (see the section called “git-config(1)”).
Moved lines of code are colored differently. The <mode> defaults to no if the option is not given and to zebra if the option with no mode is given. The mode must be one of:
This configures how whitespace is ignored when performing the move detection for --color-moved. These modes can be given as a comma separated list:
By default, words are delimited by whitespace; see --word-diff-regex below. The <mode> defaults to plain, and must be one of:
[-removed-] and {added}. Makes no
attempts to escape the delimiters if they appear in the input,
so the output may be ambiguous.
Note that despite the name of the first mode, color is used to highlight the changed parts in all modes if enabled.
Use <regex> to decide what a word is, instead of considering runs of non-whitespace to be a word. Also implies --word-diff unless it was already enabled.
Every non-overlapping match of the <regex> is considered a word. Anything between these matches is considered whitespace and ignored(!) for the purposes of finding differences. You may want to append |[^[:space:]] to your regular expression to make sure that it matches all non-whitespace characters. A match that contains a newline is silently truncated(!) at the newline.
For example, --word-diff-regex=. will treat each character as a word and, correspondingly, show differences character by character.
The regex can also be set via a diff driver or configuration option, see the section called “gitattributes(5)” or the section called “git-config(1)”. Giving it explicitly overrides any diff driver or configuration setting. Diff drivers override configuration settings.
Break complete rewrite changes into pairs of delete and create. This serves two purposes:
It affects the way a change that amounts to a total rewrite of a file not as a series of deletion and insertion mixed together with a very few lines that happen to match textually as the context, but as a single deletion of everything old followed by a single insertion of everything new, and the number <m> controls this aspect of the -B option (defaults to 60%). -B/70% specifies that less than 30% of the original should remain in the result for Git to consider it a total rewrite (i.e. otherwise the resulting patch will be a series of deletion and insertion mixed together with context lines).
When used with -M, a totally-rewritten file is also considered as the source of a rename (usually -M only considers a file that disappeared as the source of a rename), and the number <n> controls this aspect of the -B option (defaults to 50%). -B20% specifies that a change with addition and deletion compared to 20% or more of the file's size are eligible for being picked up as a possible source of a rename to another file.
Omit the preimage for deletes, i.e. print only the header but not the diff between the preimage and /dev/null. The resulting patch is not meant to be applied with patch or git apply; this is solely for people who want to just concentrate on reviewing the text after the change. In addition, the output obviously lacks enough information to apply such a patch in reverse, even manually, hence the name of the option.
When used together with -B, omit also the preimage in the deletion part of a delete/create pair.
Select only files that are Added (A), Copied (C), Deleted (D), Modified (M), Renamed (R), have their type (i.e. regular file, symlink, submodule, …) changed (T), are Unmerged (U), are Unknown (X), or have had their pairing Broken (B). Any combination of the filter characters (including none) can be used. When * (All-or-none) is added to the combination, all paths are selected if there is any file that matches other criteria in the comparison; if there is no file that matches other criteria, nothing is selected.
Also, these upper-case letters can be downcased to exclude. E.g. --diff-filter=ad excludes added and deleted paths.
Note that not all diffs can feature all types. For instance, copied and renamed entries cannot appear if detection for those types is disabled.
Look for differences that change the number of occurrences of the specified <string> (i.e. addition/deletion) in a file. Intended for the scripter's use.
It is useful when you're looking for an exact block of code (like a struct), and want to know the history of that block since it first came into being: use the feature iteratively to feed the interesting block in the preimage back into -S, and keep going until you get the very first version of the block.
Binary files are searched as well.
Look for differences whose patch text contains added/removed lines that match <regex>.
To illustrate the difference between -S<regex> --pickaxe-regex and -G<regex>, consider a commit with the following diff in the same file:
+ return frotz(nitfol, two->ptr, 1, 0); ... - hit = frotz(nitfol, mf2.ptr, 1, 0);
While git log -G"frotz\(nitfol" will show this commit, git log -S"frotz\(nitfol" --pickaxe-regex will not (because the number of occurrences of that string did not change).
Unless --text is supplied patches of binary files without a textconv filter will be ignored.
See the pickaxe entry in the section called “gitdiffcore(7)” for more information.
Look for differences that change the number of occurrences of the specified object. Similar to -S, just the argument is different in that it doesn't search for a specific string but for a specific object id.
The object can be a blob or a submodule commit. It implies the -t option in git-log to also find trees.
Control the order in which files appear in the output. This overrides the diff.orderFile configuration variable (see the section called “git-config(1)”). To cancel diff.orderFile, use -O/dev/null.
The output order is determined by the order of glob patterns in <orderfile>. All files with pathnames that match the first pattern are output first, all files with pathnames that match the second pattern (but not the first) are output next, and so on. All files with pathnames that do not match any pattern are output last, as if there was an implicit match-all pattern at the end of the file. If multiple pathnames have the same rank (they match the same pattern but no earlier patterns), their output order relative to each other is the normal order.
<orderfile> is parsed as follows:
Patterns have the same syntax and semantics as patterns used for fnmatch(3) without the FNM_PATHNAME flag, except a pathname also matches a pattern if removing any number of the final pathname components matches the pattern. For example, the pattern "foo*bar" matches "fooasdfbar" and "foo/bar/baz/asdf" but not "foobarx".
For more detailed explanation on these common options, see also the section called “gitdiffcore(7)”.
Running the section called “git-diff(1)”, the section called “git-log(1)”, the section called “git-show(1)”, the section called “git-diff-index(1)”, the section called “git-diff-tree(1)”, or the section called “git-diff-files(1)” with the -p option produces patch text. You can customize the creation of patch text via the GIT_EXTERNAL_DIFF and the GIT_DIFF_OPTS environment variables (see the section called “git(1)”), and the diff attribute (see the section called “gitattributes(5)”).
What the -p option produces is slightly different from the traditional diff format:
It is preceded by a "git diff" header that looks like this:
diff --git a/file1 b/file2
The a/ and b/ filenames are the same unless rename/copy is involved. Especially, even for a creation or a deletion, /dev/null is not used in place of the a/ or b/ filenames.
When a rename/copy is involved, file1 and file2 show the name of the source file of the rename/copy and the name of the file that the rename/copy produces, respectively.
It is followed by one or more extended header lines:
oldmode<mode>
newmode<mode>
deletedfilemode<mode>
newfilemode<mode>
copyfrom<path>
copyto<path>
renamefrom<path>
renameto<path>
similarityindex<number>
dissimilarityindex<number>
index<hash>..<hash> <mode>
File modes <mode> are printed as 6-digit octal numbers including the file type and file permission bits.
Path names in extended headers do not include the a/ and b/ prefixes.
The similarity index is the percentage of unchanged lines, and the dissimilarity index is the percentage of changed lines. It is a rounded down integer, followed by a percent sign. The similarity index value of 100% is thus reserved for two equal files, while 100% dissimilarity means that no line from the old file made it into the new one.
The index line includes the blob object names before and after the change. The <mode> is included if the file mode does not change; otherwise, separate lines indicate the old and the new mode.
All the file1 files in the output refer to files before the commit, and all the file2 files refer to files after the commit. It is incorrect to apply each change to each file sequentially. For example, this patch will swap a and b:
diff --git a/a b/b rename from a rename to b diff --git a/b b/a rename from b rename to a
Any diff-generating command can take the -c or --cc option to produce a combined diff when showing a merge. This is the default format when showing merges with the section called “git-diff(1)” or the section called “git-show(1)”. Note also that you can give suitable --diff-merges option to any of these commands to force generation of diffs in a specific format.
A "combined diff" format looks like this:
diff --combined describe.c
index fabadb8,cc95eb0..4866510
--- a/describe.c
+++ b/describe.c
@@@ -98,20 -98,12 +98,20 @@@
return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1;
}
- static void describe(char *arg)
-static void describe(struct commit *cmit, int last_one)
++static void describe(char *arg, int last_one)
{
+ unsigned char sha1[20];
+ struct commit *cmit;
struct commit_list *list;
static int initialized = 0;
struct commit_name *n;
+ if (get_sha1(arg, sha1) < 0)
+ usage(describe_usage);
+ cmit = lookup_commit_reference(sha1);
+ if (!cmit)
+ usage(describe_usage);
+
if (!initialized) {
initialized = 1;
for_each_ref(get_name);It is preceded by a "git diff" header, that looks like this (when the -c option is used):
diff --combined file
or like this (when the --cc option is used):
diff --cc file
It is followed by one or more extended header lines (this example shows a merge with two parents):
index<hash>,<hash>..<hash>
mode<mode>,<mode>..<mode>
newfilemode<mode>
deletedfilemode<mode>,<mode>
The mode <mode>,<mode>..<mode> line appears only if at least one of the <mode> is different from the rest. Extended headers with information about detected content movement (renames and copying detection) are designed to work with the diff of two <tree-ish> and are not used by combined diff format.
It is followed by a two-line from-file/to-file header:
--- a/file +++ b/file
Similar to the two-line header for the traditional unified diff format, /dev/null is used to signal created or deleted files.
However, if the --combined-all-paths option is provided, instead of a two-line from-file/to-file, you get an N+1 line from-file/to-file header, where N is the number of parents in the merge commit:
--- a/file --- a/file --- a/file +++ b/file
This extended format can be useful if rename or copy detection is active, to allow you to see the original name of the file in different parents.
Chunk header format is modified to prevent people from accidentally feeding it to patch -p1. Combined diff format was created for review of merge commit changes, and was not meant to be applied. The change is similar to the change in the extended index header:
@@@ <from-file-range> <from-file-range> <to-file-range> @@@
There are (number of parents + 1) @ characters in the chunk header for combined diff format.
Unlike the traditional unified diff format, which shows two files A and B with a single column that has - (minus -- appears in A but removed in B), + (plus -- missing in A but added to B), or " " (space -- unchanged) prefix, this format compares two or more files file1, file2,… with one file X, and shows how X differs from each of fileN. One column for each of fileN is prepended to the output line to note how X's line is different from it.
A - character in the column N means that the line appears in fileN but it does not appear in the result. A + character in the column N means that the line appears in the result, and fileN does not have that line (in other words, the line was added, from the point of view of that parent).
In the above example output, the function signature was changed from both files (hence two - removals from both file1 and file2, plus ++ to mean one line that was added does not appear in either file1 or file2). Also, eight other lines are the same from file1 but do not appear in file2 (hence prefixed with +).
When shown by git diff-tree -c, it compares the parents of a merge commit with the merge result (i.e. file1..fileN are the parents). When shown by git diff-files -c, it compares the two unresolved merge parents with the working tree file (i.e. file1 is stage 2 aka "our version", file2 is stage 3 aka "their version").
Git is to some extent character encoding agnostic.
Path names are encoded in UTF-8 normalization form C. This applies to tree objects, the index file, ref names, as well as path names in command line arguments, environment variables and config files (.git/config (see the section called “git-config(1)”), the section called “gitignore(5)”, the section called “gitattributes(5)” and the section called “gitmodules(5)”).
Note that Git at the core level treats path names simply as sequences of non-NUL bytes, there are no path name encoding conversions (except on Mac and Windows). Therefore, using non-ASCII path names will mostly work even on platforms and file systems that use legacy extended ASCII encodings. However, repositories created on such systems will not work properly on UTF-8-based systems (e.g. Linux, Mac, Windows) and vice versa. Additionally, many Git-based tools simply assume path names to be UTF-8 and will fail to display other encodings correctly.
Although we encourage that the commit log messages are encoded in UTF-8, both the core and Git Porcelain are designed not to force UTF-8 on projects. If all participants of a particular project find it more convenient to use legacy encodings, Git does not forbid it. However, there are a few things to keep in mind.
git commit and git commit-tree issue a warning if the commit log message given to it does not look like a valid UTF-8 string, unless you explicitly say your project uses a legacy encoding. The way to say this is to have i18n.commitEncoding in .git/config file, like this:
[i18n]
commitEncoding = ISO-8859-1Commit objects created with the above setting record the value of i18n.commitEncoding in their encoding header. This is to help other people who look at them later. Lack of this header implies that the commit log message is encoded in UTF-8.
git log, git show, git blame and friends look at the encoding header of a commit object, and try to re-code the log message into UTF-8 unless otherwise specified. You can specify the desired output encoding with i18n.logOutputEncoding in .git/config file, like this:
[i18n]
logOutputEncoding = ISO-8859-1If you do not have this configuration variable, the value of i18n.commitEncoding is used instead.
Note that we deliberately chose not to re-code the commit log message when a commit is made to force UTF-8 at the commit object level, because re-coding to UTF-8 is not necessarily a reversible operation.
Part of the the section called “git(1)” suite
This command is used to create sparse checkouts, which change the working tree from having all tracked files present to only having a subset of those files. It can also switch which subset of files are present, or undo and go back to having all tracked files present in the working copy.
The subset of files is chosen by providing a list of directories in cone mode (the default), or by providing a list of patterns in non-cone mode.
When in a sparse-checkout, other Git commands behave a bit differently. For example, switching branches will not update paths outside the sparse-checkout directories/patterns, and git commit -a will not record paths outside the sparse-checkout directories/patterns as deleted.
THIS COMMAND IS EXPERIMENTAL. ITS BEHAVIOR, AND THE BEHAVIOR OF OTHER COMMANDS IN THE PRESENCE OF SPARSE-CHECKOUTS, WILL LIKELY CHANGE IN THE FUTURE.
Enable the necessary sparse-checkout config settings (core.sparseCheckout, core.sparseCheckoutCone, and index.sparse) if they are not already set to the desired values, populate the sparse-checkout file from the list of arguments following the set subcommand, and update the working directory to match.
To ensure that adjusting the sparse-checkout settings within a worktree does not alter the sparse-checkout settings in other worktrees, the set subcommand will upgrade your repository config to use worktree-specific config if not already present. The sparsity defined by the arguments to the set subcommand are stored in the worktree-specific sparse-checkout file. See the section called “git-worktree(1)” and the documentation of extensions.worktreeConfig in the section called “git-config(1)” for more details.
When the --stdin option is provided, the directories or patterns are read from standard in as a newline-delimited list instead of from the arguments.
By default, the input list is considered a list of directories, matching the output of git ls-tree -d --name-only. This includes interpreting pathnames that begin with a double quote (") as C-style quoted strings. Note that all files under the specified directories (at any depth) will be included in the sparse checkout, as well as files that are siblings of either the given directory or any of its ancestors (see CONE PATTERN SET below for more details). In the past, this was not the default, and --cone needed to be specified or core.sparseCheckoutCone needed to be enabled.
When --no-cone is passed, the input list is considered a list of patterns. This mode has a number of drawbacks, including not working with some options like --sparse-index. As explained in the "Non-cone Problems" section below, we do not recommend using it.
Use the --[no-]sparse-index option to use a sparse index (the default is to not use it). A sparse index reduces the size of the index to be more closely aligned with your sparse-checkout definition. This can have significant performance advantages for commands such as git status or git add. This feature is still experimental. Some commands might be slower with a sparse index until they are properly integrated with the feature.
WARNING: Using a sparse index requires modifying the index in a way that is not completely understood by external tools. If you have trouble with this compatibility, then run git sparse-checkout init --no-sparse-index to rewrite your index to not be sparse. Older versions of Git will not understand the sparse directory entries index extension and may fail to interact with your repository until it is disabled.
Reapply the sparsity pattern rules to paths in the working tree. Commands like merge or rebase can materialize paths to do their work (e.g. in order to show you a conflict), and other sparse-checkout commands might fail to sparsify an individual file (e.g. because it has unstaged changes or conflicts). In such cases, it can make sense to run git sparse-checkout reapply later after cleaning up affected paths (e.g. resolving conflicts, undoing or committing changes, etc.).
The reapply command can also take --[no-]cone and --[no-]sparse-index flags, with the same meaning as the flags from the set command, in order to change which sparsity mode you are using without needing to also respecify all sparsity paths.
Deprecated command that behaves like set with no specified paths. May be removed in the future.
Historically, set did not handle all the necessary config settings, which meant that both init and set had to be called. Invoking both meant the init step would first remove nearly all tracked files (and in cone mode, ignored files too), then the set step would add many of the tracked files (but not ignored files) back. In addition to the lost files, the performance and UI of this combination was poor.
Also, historically, init would not actually initialize the sparse-checkout file if it already existed. This meant it was possible to return to a sparse-checkout without remembering which paths to pass to a subsequent set or add command. However, --cone and --sparse-index options would not be remembered across the disable command, so the easy restore of calling a plain init decreased in utility.
Check whether sparsity rules match one or more paths.
By default check-rules reads a list of paths from stdin and outputs only the ones that match the current sparsity rules. The input is expected to consist of one path per line, matching the output of git ls-tree --name-only including that pathnames that begin with a double quote (") are interpreted as C-style quoted strings.
When called with the --rules-file <file> flag the input files are matched against the sparse checkout rules found in <file> instead of the current ones. The rules in the files are expected to be in the same form as accepted by git sparse-checkout set --stdin (in particular, they must be newline-delimited).
By default, the rules passed to the --rules-file option are interpreted as cone mode directories. To pass non-cone mode patterns with --rules-file, combine the option with the --no-cone option.
When called with the -z flag, the format of the paths input on stdin as well as the output paths are \0 terminated and not quoted. Note that this does not apply to the format of the rules passed with the --rules-file option.
"Sparse checkout" allows populating the working directory sparsely. It uses the skip-worktree bit (see the section called “git-update-index(1)”) to tell Git whether a file in the working directory is worth looking at. If the skip-worktree bit is set, and the file is not present in the working tree, then its absence is ignored. Git will avoid populating the contents of those files, which makes a sparse checkout helpful when working in a repository with many files, but only a few are important to the current user.
The $GIT_DIR/info/sparse-checkout file is used to define the skip-worktree reference bitmap. When Git updates the working directory, it updates the skip-worktree bits in the index based on this file. The files matching the patterns in the file will appear in the working directory, and the rest will not.
The $GIT_DIR/info/sparse-checkout file populated by the set and add subcommands is defined to be a bunch of patterns (one per line) using the same syntax as .gitignore files. In cone mode, these patterns are restricted to matching directories (and users only ever need supply or see directory names), while in non-cone mode any gitignore-style pattern is permitted. Using the full gitignore-style patterns in non-cone mode has a number of shortcomings:
It has edge cases where the "right" behavior is unclear. Two examples:
First, two users are in a subdirectory, and the first runs git sparse-checkout set '/toplevel-dir/*.c' while the second runs git sparse-checkout set relative-dir Should those arguments be transliterated into current/subdirectory/toplevel-dir/*.c and current/subdirectory/relative-dir before inserting into the sparse-checkout file? The user who typed the first command is probably aware that arguments to set/add are supposed to be patterns in non-cone mode, and probably would not be happy with such a transliteration. However, many gitignore-style patterns are just paths, which might be what the user who typed the second command was thinking, and they'd be upset if their argument wasn't transliterated.
Second, what should bash-completion complete on for set/add commands for non-cone users? If it suggests paths, is it exacerbating the problem above? Also, if it suggests paths, what if the user has a file or directory that begins with either a '!' or '#' or has a '*', '\', '?', '[', or ']' in its name? And if it suggests paths, will it complete "/pro" to "/proc" (in the root filesystem) rather than to "/progress.txt" in the current directory? (Note that users are likely to want to start paths with a leading '/' in non-cone mode, for the same reason that .gitignore files often have one.) Completing on files or directories might give nasty surprises in all these cases.
For all these reasons, non-cone mode is deprecated. Please switch to using cone mode.
The "cone mode", which is the default, lets you specify only what directories to include. For any directory specified, all paths below that directory will be included, and any paths immediately under leading directories (including the toplevel directory) will also be included. Thus, if you specified the directory Documentation/technical/ then your sparse checkout would contain:
Also, in cone mode, even if no directories are specified, then the files in the toplevel directory will be included.
When changing the sparse-checkout patterns in cone mode, Git will inspect each tracked directory that is not within the sparse-checkout cone to see if it contains any untracked files. If all of those files are ignored due to the .gitignore patterns, then the directory will be deleted. If any of the untracked files within that directory is not ignored, then no deletions will occur within that directory and a warning message will appear. If these files are important, then reset your sparse-checkout definition so they are included, use git add and git commit to store them, then remove any remaining files manually to ensure Git can behave optimally.
See also the "Internals -- Cone Pattern Set" section to learn how the directories are transformed under the hood into a subset of the Full Pattern Set of sparse-checkout.
The full pattern set allows for arbitrary pattern matches and complicated inclusion/exclusion rules. These can result in O(N*M) pattern matches when updating the index, where N is the number of patterns and M is the number of paths in the index. To combat this performance issue, a more restricted pattern set is allowed when core.sparseCheckoutCone is enabled.
The sparse-checkout file uses the same syntax as .gitignore files; see the section called “gitignore(5)” for details. Here, though, the patterns are usually being used to select which files to include rather than which files to exclude. (However, it can get a bit confusing since gitignore-style patterns have negations defined by patterns which begin with a !, so you can also select files to not include.)
For example, to select everything, and then to remove the file unwanted (so that every file will appear in your working tree except the file named unwanted):
git sparse-checkout set --no-cone '/*' '!unwanted'
These patterns are just placed into the $GIT_DIR/info/sparse-checkout as-is, so the contents of that file at this point would be
/* !unwanted
See also the "Sparse Checkout" section of the section called “git-read-tree(1)” to learn more about the gitignore-style patterns used in sparse checkouts.
In cone mode, only directories are accepted, but they are translated into the same gitignore-style patterns used in the full pattern set. We refer to the particular patterns used in those mode as being of one of two types:
Since cone mode always includes files at the toplevel, when running git sparse-checkout set with no directories specified, the toplevel directory is added as a parent pattern. At this point, the sparse-checkout file contains the following patterns:
/* !/*/
This says "include everything immediately under the toplevel directory, but nothing at any level below that."
When in cone mode, the git sparse-checkout set subcommand takes a list of directories. The command git sparse-checkout set A/B/C sets the directory A/B/C as a recursive pattern, the directories A and A/B are added as parent patterns. The resulting sparse-checkout file is now
/* !/*/ /A/ !/A/*/ /A/B/ !/A/B/*/ /A/B/C/
Here, order matters, so the negative patterns are overridden by the positive patterns that appear lower in the file.
Unless core.sparseCheckoutCone is explicitly set to false, Git will parse the sparse-checkout file expecting patterns of these types. Git will warn if the patterns do not match. If the patterns do match the expected format, then Git will use faster hash-based algorithms to compute inclusion in the sparse-checkout. If they do not match, git will behave as though core.sparseCheckoutCone was false, regardless of its setting.
In the cone mode case, despite the fact that full patterns are written to the $GIT_DIR/info/sparse-checkout file, the git sparse-checkout list subcommand will list the directories that define the recursive patterns. For the example sparse-checkout file above, the output is as follows:
$ git sparse-checkout list A/B/C
If core.ignoreCase=true, then the pattern-matching algorithm will use a case-insensitive check. This corrects for case mismatched filenames in the git sparse-checkout set command to reflect the expected cone in the working directory.
If your repository contains one or more submodules, then submodules are populated based on interactions with the git submodule command. Specifically, git submodule init -- <path> will ensure the submodule at <path> is present, while git submodule deinit [-f] -- <path> will remove the files for the submodule at <path> (including any untracked files, uncommitted changes, and unpushed history). Similar to how sparse-checkout removes files from the working tree but still leaves entries in the index, deinitialized submodules are removed from the working directory but still have an entry in the index.
Since submodules may have unpushed changes or untracked files, removing them could result in data loss. Thus, changing sparse inclusion/exclusion rules will not cause an already checked out submodule to be removed from the working copy. Said another way, just as checkout will not cause submodules to be automatically removed or initialized even when switching between branches that remove or add submodules, using sparse-checkout to reduce or expand the scope of "interesting" files will not cause submodules to be automatically deinitialized or initialized either.
Further, the above facts mean that there are multiple reasons that "tracked" files might not be present in the working copy: sparsity pattern application from sparse-checkout, and submodule initialization state. Thus, commands like git grep that work on tracked files in the working copy may return results that are limited by either or both of these restrictions.
Part of the the section called “git(1)” suite
This is a synonym for the section called “git-add(1)”. Please refer to the documentation of that command.
Part of the the section called “git(1)” suite
git stash list [<log-options>]
git stash show [-u | --include-untracked | --only-untracked] [<diff-options>] [<stash>]
git stash drop [-q | --quiet] [<stash>]
git stash pop [--index] [-q | --quiet] [<stash>]
git stash apply [--index] [-q | --quiet] [<stash>]
git stash branch <branchname> [<stash>]
git stash [push [-p | --patch] [-S | --staged] [-k | --[no-]keep-index] [-q | --quiet]
[-u | --include-untracked] [-a | --all] [(-m | --message) <message>]
[--pathspec-from-file=<file> [--pathspec-file-nul]]
[--] [<pathspec>…]]
git stash save [-p | --patch] [-S | --staged] [-k | --[no-]keep-index] [-q | --quiet]
[-u | --include-untracked] [-a | --all] [<message>]
git stash clear
git stash create [<message>]
git stash store [(-m | --message) <message>] [-q | --quiet] <commit>
Use git stash when you want to record the current state of the working directory and the index, but want to go back to a clean working directory. The command saves your local modifications away and reverts the working directory to match the HEAD commit.
The modifications stashed away by this command can be listed with git stash list, inspected with git stash show, and restored (potentially on top of a different commit) with git stash apply. Calling git stash without any arguments is equivalent to git stash push. A stash is by default listed as "WIP on branchname …", but you can give a more descriptive message on the command line when you create one.
The latest stash you created is stored in refs/stash; older stashes are found in the reflog of this reference and can be named using the usual reflog syntax (e.g. stash@{0} is the most recently created stash, stash@{1} is the one before it, stash@{2.hours.ago} is also possible). Stashes may also be referenced by specifying just the stash index (e.g. the integer n is equivalent to stash@{n}).
Save your local modifications to a new stash entry and roll them back to HEAD (in the working tree and in the index). The <message> part is optional and gives the description along with the stashed state.
For quickly making a snapshot, you can omit "push". In this mode, non-option arguments are not allowed to prevent a misspelled subcommand from making an unwanted stash entry. The two exceptions to this are stash -p which acts as alias for stash push -p and pathspec elements, which are allowed after a double hyphen -- for disambiguation.
List the stash entries that you currently have. Each stash entry is listed with its name (e.g. stash@{0} is the latest entry, stash@{1} is the one before, etc.), the name of the branch that was current when the entry was made, and a short description of the commit the entry was based on.
stash@{0}: WIP on submit: 6ebd0e2... Update git-stash documentation
stash@{1}: On master: 9cc0589... Add git-stashThe command takes options applicable to the git log command to control what is shown and how. See the section called “git-log(1)”.
Remove a single stashed state from the stash list and apply it on top of the current working tree state, i.e., do the inverse operation of git stash push. The working directory must match the index.
Applying the state can fail with conflicts; in this case, it is not removed from the stash list. You need to resolve the conflicts by hand and call git stash drop manually afterwards.
Creates and checks out a new branch named <branchname> starting from the commit at which the <stash> was originally created, applies the changes recorded in <stash> to the new working tree and index. If that succeeds, and <stash> is a reference of the form stash@{<revision>}, it then drops the <stash>.
This is useful if the branch on which you ran git stash push has changed enough that git stash apply fails due to conflicts. Since the stash entry is applied on top of the commit that was HEAD at the time git stash was run, it restores the originally stashed state with no conflicts.
This option is only valid for push and save commands.
All ignored and untracked files are also stashed and then cleaned up with git clean.
When used with the push and save commands, all untracked files are also stashed and then cleaned up with git clean.
When used with the show command, show the untracked files in the stash entry as part of the diff.
This option is only valid for the show command.
Show only the untracked files in the stash entry as part of the diff.
This option is only valid for pop and apply commands.
Tries to reinstate not only the working tree's changes, but also the index's ones. However, this can fail, when you have conflicts (which are stored in the index, where you therefore can no longer apply the changes as they were originally).
This option is only valid for push and save commands.
All changes already added to the index are left intact.
This option is only valid for push and save commands.
Interactively select hunks from the diff between HEAD and the working tree to be stashed. The stash entry is constructed such that its index state is the same as the index state of your repository, and its worktree contains only the changes you selected interactively. The selected changes are then rolled back from your worktree. See the Interactive Mode section of the section called “git-add(1)” to learn how to operate the --patch mode.
The --patch option implies --keep-index. You can use --no-keep-index to override this.
This option is only valid for push and save commands.
Stash only the changes that are currently staged. This is similar to basic git commit except the state is committed to the stash instead of current branch.
The --patch option has priority over this one.
This option is only valid for push command.
Pathspec is passed in <file> instead of commandline args. If <file> is exactly - then standard input is used. Pathspec elements are separated by LF or CR/LF. Pathspec elements can be quoted as explained for the configuration variable core.quotePath (see the section called “git-config(1)”). See also --pathspec-file-nul and global --literal-pathspecs.
This option is only valid for push command.
Only meaningful with --pathspec-from-file. Pathspec elements are separated with NUL character and all other characters are taken literally (including newlines and quotes).
This option is only valid for apply, drop, pop, push, save, store commands.
Quiet, suppress feedback messages.
This option is only valid for push command.
Separates pathspec from options for disambiguation purposes.
This option is only valid for push command.
The new stash entry records the modified states only for the files that match the pathspec. The index entries and working tree files are then rolled back to the state in HEAD only for these files, too, leaving files that do not match the pathspec intact.
For more details, see the pathspec entry in the section called “gitglossary(7)”.
This option is only valid for apply, branch, drop, pop, show commands.
A reference of the form stash@{<revision>}. When no <stash> is given, the latest stash is assumed (that is, stash@{0}).
A stash entry is represented as a commit whose tree records the state of the working directory, and its first parent is the commit at HEAD when the entry was created. The tree of the second parent records the state of the index when the entry is made, and it is made a child of the HEAD commit. The ancestry graph looks like this:
.----W
/ /
-----H----Iwhere H is the HEAD commit, I is a commit that records the state of the index, and W is a commit that records the state of the working tree.
When you are in the middle of something, you learn that there are upstream changes that are possibly relevant to what you are doing. When your local changes do not conflict with the changes in the upstream, a simple git pull will let you move forward.
However, there are cases in which your local changes do conflict with the upstream changes, and git pull refuses to overwrite your changes. In such a case, you can stash your changes away, perform a pull, and then unstash, like this:
$ git pull ... file foobar not up to date, cannot merge. $ git stash $ git pull $ git stash pop
When you are in the middle of something, your boss comes in and demands that you fix something immediately. Traditionally, you would make a commit to a temporary branch to store your changes away, and return to your original branch to make the emergency fix, like this:
# ... hack hack hack ... $ git switch -c my_wip $ git commit -a -m "WIP" $ git switch master $ edit emergency fix $ git commit -a -m "Fix in a hurry" $ git switch my_wip $ git reset --soft HEAD^ # ... continue hacking ...
You can use git stash to simplify the above, like this:
# ... hack hack hack ... $ git stash $ edit emergency fix $ git commit -a -m "Fix in a hurry" $ git stash pop # ... continue hacking ...
You can use git stash push --keep-index when you want to make two or more commits out of the changes in the work tree, and you want to test each change before committing:
# ... hack hack hack ... $ git add --patch foo # add just first part to the index $ git stash push --keep-index # save all other changes to the stash $ edit/build/test first part $ git commit -m 'First part' # commit fully tested change $ git stash pop # prepare to work on all other changes # ... repeat above five steps until one commit remains ... $ edit/build/test remaining parts $ git commit foo -m 'Remaining parts'
When you are in the middle of massive changes and you find some unrelated issue that you don't want to forget to fix, you can do the change(s), stage them, and use git stash push --staged to stash them out for future use. This is similar to committing the staged changes, only the commit ends-up being in the stash and not on the current branch.
# ... hack hack hack ... $ git add --patch foo # add unrelated changes to the index $ git stash push --staged # save these changes to the stash # ... hack hack hack, finish current changes ... $ git commit -m 'Massive' # commit fully tested changes $ git switch fixup-branch # switch to another branch $ git stash pop # to finish work on the saved changes
If you mistakenly drop or clear stash entries, they cannot be recovered through the normal safety mechanisms. However, you can try the following incantation to get a list of stash entries that are still in your repository, but not reachable any more:
git fsck --unreachable | grep commit | cut -d\ -f3 | xargs git log --merges --no-walk --grep=WIP
Everything below this line in this section is selectively included from the the section called “git-config(1)” documentation. The content is the same as what's found there:
the section called “git-checkout(1)”, the section called “git-commit(1)”, the section called “git-reflog(1)”, the section called “git-reset(1)”, the section called “git-switch(1)”
Part of the the section called “git(1)” suite
Displays paths that have differences between the index file and the current HEAD commit, paths that have differences between the working tree and the index file, and paths in the working tree that are not tracked by Git (and are not ignored by the section called “gitignore(5)”). The first are what you would commit by running git commit; the second and third are what you could commit by running git add before running git commit.
Give the output in an easy-to-parse format for scripts. This is similar to the short output, but will remain stable across Git versions and regardless of user configuration. See below for details.
The version parameter is used to specify the format version. This is optional and defaults to the original version v1 format.
Show untracked files.
The mode parameter is used to specify the handling of untracked files. It is optional: it defaults to all, and if specified, it must be stuck to the option (e.g. -uno, but not -u no).
The possible options are:
When -u option is not used, untracked files and directories are shown (i.e. the same as specifying normal), to help you avoid forgetting to add newly created files. Because it takes extra work to find untracked files in the filesystem, this mode may take some time in a large working tree. Consider enabling untracked cache and split index if supported (see git update-index --untracked-cache and git update-index --split-index), Otherwise you can use no to have git status return more quickly without showing untracked files. All usual spellings for Boolean value true are taken as normal and false as no.
The default can be changed using the status.showUntrackedFiles configuration variable documented in the section called “git-config(1)”.
Show ignored files as well.
The mode parameter is used to specify the handling of ignored files. It is optional: it defaults to traditional.
The possible options are:
When matching mode is specified, paths that explicitly match an ignored pattern are shown. If a directory matches an ignore pattern, then it is shown, but not paths contained in the ignored directory. If a directory does not match an ignore pattern, but all contents are ignored, then the directory is not shown, but all contents are shown.
The output from this command is designed to be used as a commit template comment. The default, long format, is designed to be human readable, verbose and descriptive. Its contents and format are subject to change at any time.
The paths mentioned in the output, unlike many other Git commands, are made relative to the current directory if you are working in a subdirectory (this is on purpose, to help cutting and pasting). See the status.relativePaths config option below.
In the short-format, the status of each path is shown as one of these forms
XY PATH XY ORIG_PATH -> PATH
where ORIG_PATH is where the renamed/copied contents came from. ORIG_PATH is only shown when the entry is renamed or copied. The XY is a two-letter status code.
The fields (including the ->) are separated from each other by a single space. If a filename contains whitespace or other nonprintable characters, that field will be quoted in the manner of a C string literal: surrounded by ASCII double quote (34) characters, and with interior special characters backslash-escaped.
There are three different types of states that are shown using this format, and each one uses the XY syntax differently:
Note that the term merge here also includes rebases using the default --merge strategy, cherry-picks, and anything else using the merge machinery.
In the following table, these three classes are shown in separate sections, and these characters are used for X and Y fields for the first two sections that show tracked paths:
X Y Meaning
-------------------------------------------------
[AMD] not updated
M [ MTD] updated in index
T [ MTD] type changed in index
A [ MTD] added to index
D deleted from index
R [ MTD] renamed in index
C [ MTD] copied in index
[MTARC] index and work tree matches
[ MTARC] M work tree changed since index
[ MTARC] T type changed in work tree since index
[ MTARC] D deleted in work tree
R renamed in work tree
C copied in work tree
-------------------------------------------------
D D unmerged, both deleted
A U unmerged, added by us
U D unmerged, deleted by them
U A unmerged, added by them
D U unmerged, deleted by us
A A unmerged, both added
U U unmerged, both modified
-------------------------------------------------
? ? untracked
! ! ignored
-------------------------------------------------Submodules have more state and instead report
This is since modified content or untracked files in a submodule cannot be added via git add in the superproject to prepare a commit.
m and ? are applied recursively. For example if a nested submodule in a submodule contains an untracked file, this is reported as ? as well.
If -b is used the short-format status is preceded by a line
## branchname tracking info
Version 1 porcelain format is similar to the short format, but is guaranteed not to change in a backwards-incompatible way between Git versions or based on user configuration. This makes it ideal for parsing by scripts. The description of the short format above also describes the porcelain format, with a few exceptions:
There is also an alternate -z format recommended for machine parsing. In that format, the status field is the same, but some other things change. First, the -> is omitted from rename entries and the field order is reversed (e.g from -> to becomes to from). Second, a NUL (ASCII 0) follows each filename, replacing space as a field separator and the terminating newline (but a space still separates the status field from the first filename). Third, filenames containing special characters are not specially formatted; no quoting or backslash-escaping is performed.
Any submodule changes are reported as modified M instead of m or single ?.
Version 2 format adds more detailed information about the state of the worktree and changed items. Version 2 also defines an extensible set of easy to parse optional headers.
Header lines start with "#" and are added in response to specific command line arguments. Parsers should ignore headers they don't recognize.
If --branch is given, a series of header lines are printed with information about the current branch.
Line Notes
------------------------------------------------------------
# branch.oid <commit> | (initial) Current commit.
# branch.head <branch> | (detached) Current branch.
# branch.upstream <upstream-branch> If upstream is set.
# branch.ab +<ahead> -<behind> If upstream is set and
the commit is present.
------------------------------------------------------------If --show-stash is given, one line is printed showing the number of stash entries if non-zero:
# stash <N>
Following the headers, a series of lines are printed for tracked entries. One of three different line formats may be used to describe an entry depending on the type of change. Tracked entries are printed in an undefined order; parsers should allow for a mixture of the 3 line types in any order.
Ordinary changed entries have the following format:
1 <XY> <sub> <mH> <mI> <mW> <hH> <hI> <path>
Renamed or copied entries have the following format:
2 <XY> <sub> <mH> <mI> <mW> <hH> <hI> <X><score> <path><sep><origPath>
Field Meaning
--------------------------------------------------------
<XY> A 2 character field containing the staged and
unstaged XY values described in the short format,
with unchanged indicated by a "." rather than
a space.
<sub> A 4 character field describing the submodule state.
"N..." when the entry is not a submodule.
"S<c><m><u>" when the entry is a submodule.
<c> is "C" if the commit changed; otherwise ".".
<m> is "M" if it has tracked changes; otherwise ".".
<u> is "U" if there are untracked changes; otherwise ".".
<mH> The octal file mode in HEAD.
<mI> The octal file mode in the index.
<mW> The octal file mode in the worktree.
<hH> The object name in HEAD.
<hI> The object name in the index.
<X><score> The rename or copy score (denoting the percentage
of similarity between the source and target of the
move or copy). For example "R100" or "C75".
<path> The pathname. In a renamed/copied entry, this
is the target path.
<sep> When the `-z` option is used, the 2 pathnames are separated
with a NUL (ASCII 0x00) byte; otherwise, a tab (ASCII 0x09)
byte separates them.
<origPath> The pathname in the commit at HEAD or in the index.
This is only present in a renamed/copied entry, and
tells where the renamed/copied contents came from.
--------------------------------------------------------Unmerged entries have the following format; the first character is a "u" to distinguish from ordinary changed entries.
u <XY> <sub> <m1> <m2> <m3> <mW> <h1> <h2> <h3> <path>
Field Meaning
--------------------------------------------------------
<XY> A 2 character field describing the conflict type
as described in the short format.
<sub> A 4 character field describing the submodule state
as described above.
<m1> The octal file mode in stage 1.
<m2> The octal file mode in stage 2.
<m3> The octal file mode in stage 3.
<mW> The octal file mode in the worktree.
<h1> The object name in stage 1.
<h2> The object name in stage 2.
<h3> The object name in stage 3.
<path> The pathname.
--------------------------------------------------------Following the tracked entries (and if requested), a series of lines will be printed for untracked and then ignored items found in the worktree.
Untracked items have the following format:
? <path>
Ignored items have the following format:
! <path>
When the -z option is given, pathnames are printed as is and without any quoting and lines are terminated with a NUL (ASCII 0x00) byte.
Without the -z option, pathnames with "unusual" characters are quoted as explained for the configuration variable core.quotePath (see the section called “git-config(1)”).
The command honors color.status (or status.color -- they mean the same thing and the latter is kept for backward compatibility) and color.status.<slot> configuration variables to colorize its output.
If the config variable status.relativePaths is set to false, then all paths shown are relative to the repository root, not to the current directory.
If status.submoduleSummary is set to a non zero number or true (identical to -1 or an unlimited number), the submodule summary will be enabled for the long format and a summary of commits for modified submodules will be shown (see --summary-limit option of the section called “git-submodule(1)”). Please note that the summary output from the status command will be suppressed for all submodules when diff.ignoreSubmodules is set to all or only for those submodules where submodule.<name>.ignore=all. To also view the summary for ignored submodules you can either use the --ignore-submodules=dirty command line option or the git submodule summary command, which shows a similar output but does not honor these settings.
By default, git status will automatically refresh the index, updating the cached stat information from the working tree and writing out the result. Writing out the updated index is an optimization that isn't strictly necessary (status computes the values for itself, but writing them out is just to save subsequent programs from repeating our computation). When status is run in the background, the lock held during the write may conflict with other simultaneous processes, causing them to fail. Scripts running status in the background should consider using git --no-optional-locks status (see the section called “git(1)” for details).
git status can be very slow in large worktrees if/when it needs to search for untracked files and directories. There are many configuration options available to speed this up by either avoiding the work or making use of cached results from previous Git commands. There is no single optimum set of settings right for everyone. We'll list a summary of the relevant options to help you, but before going into the list, you may want to run git status again, because your configuration may already be caching git status results, so it could be faster on subsequent runs.
Note that after you turn on the untracked cache and/or FSMonitor features it may take a few git status commands for the various caches to warm up before you see improved command times. This is normal.
Part of the the section called “git(1)” suite
Read text, such as commit messages, notes, tags and branch descriptions, from the standard input and clean it in the manner used by Git.
With no arguments, this will:
In the case where the input consists entirely of whitespace characters, no output will be produced.
NOTE: This is intended for cleaning metadata. Prefer the --whitespace=fix mode of the section called “git-apply(1)” for correcting whitespace of patches or files in the repository.
Given the following noisy input with $ indicating the end of a line:
|A brief introduction $ | $ |$ |A new paragraph$ |# with a commented-out line $ |explaining lots of stuff.$ |$ |# An old paragraph, also commented-out. $ | $ |The end.$ | $
Use git stripspace with no arguments to obtain:
|A brief introduction$ |$ |A new paragraph$ |# with a commented-out line$ |explaining lots of stuff.$ |$ |# An old paragraph, also commented-out.$ |$ |The end.$
Use git stripspace --strip-comments to obtain:
|A brief introduction$ |$ |A new paragraph$ |explaining lots of stuff.$ |$ |The end.$
Part of the the section called “git(1)” suite
gitswitch[<options>] [--no-guess] <branch>
gitswitch[<options>]--detach[<start-point>]
gitswitch[<options>] (-c|-C) <new-branch> [<start-point>]
gitswitch[<options>]--orphan<new-branch>
Switch to a specified branch. The working tree and the index are updated to match the branch. All new commits will be added to the tip of this branch.
Optionally a new branch could be created with either -c, -C, automatically from a remote branch of same name (see --guess), or detach the working tree from any branch with --detach, along with switching.
Switching branches does not require a clean index and working tree (i.e. no differences compared to HEAD). The operation is aborted however if the operation leads to loss of local changes, unless told otherwise with --discard-changes or --merge.
THIS COMMAND IS EXPERIMENTAL. THE BEHAVIOR MAY CHANGE.
The starting point for the new branch. Specifying a <start-point> allows you to create a branch based on some other point in history than where HEAD currently points. (Or, in the case of --detach, allows you to inspect and detach from some other point.)
You can use the @{-<N>} syntax to refer to the <N>-th last branch/commit switched to using git switch or git checkout operation. You may also specify - which is synonymous to @{-1}. This is often used to switch quickly between two branches, or to undo a branch switch by mistake.
As a special case, you may use <rev-a>...<rev-b> as a shortcut for the merge base of <rev-a> and <rev-b> if there is exactly one merge base. You can leave out at most one of <rev-a> and <rev-b>, in which case it defaults to HEAD.
Create a new branch named <new-branch> starting at <start-point> before switching to the branch. This is the transactional equivalent of
$ git branch <new-branch> $ git switch <new-branch>
that is to say, the branch is not reset/created unless git switch is successful (e.g., when the branch is in use in another worktree, not just the current branch stays the same, but the branch is not reset to the start-point, either).
Similar to --create except that if <new-branch> already exists, it will be reset to <start-point>. This is a convenient shortcut for:
$ git branch -f _<new-branch>_ $ git switch _<new-branch>_
If <branch> is not found but there does exist a tracking branch in exactly one remote (call it <remote>) with a matching name, treat as equivalent to
$ git switch -c <branch> --track <remote>/<branch>
If the branch exists in multiple remotes and one of them is named by the checkout.defaultRemote configuration variable, we'll use that one for the purposes of disambiguation, even if the <branch> isn't unique across all remotes. Set it to e.g. checkout.defaultRemote=origin to always checkout remote branches from there if <branch> is ambiguous but exists on the origin remote. See also checkout.defaultRemote in the section called “git-config(1)”.
--guess is the default behavior. Use --no-guess to disable it.
The default behavior can be set via the checkout.guess configuration variable.
If you have local modifications to one or more files that are different between the current branch and the branch to which you are switching, the command refuses to switch branches in order to preserve your modifications in context. However, with this option, a three-way merge between the current branch, your working tree contents, and the new branch is done, and you will be on the new branch.
When a merge conflict happens, the index entries for conflicting paths are left unmerged, and you need to resolve the conflicts and mark the resolved paths with git add (or git rm if the merge should result in deletion of the path).
When creating a new branch, set up "upstream" configuration. -c is implied. See --track in the section called “git-branch(1)” for details.
If no -c option is given, the name of the new branch will be derived from the remote-tracking branch, by looking at the local part of the refspec configured for the corresponding remote, and then stripping the initial part up to the "*". This would tell us to use hack as the local branch when branching off of origin/hack (or remotes/origin/hack, or even refs/remotes/origin/hack). If the given name has no slash, or the above guessing results in an empty name, the guessing is aborted. You can explicitly give a name with -c in such a case.
The following command switches to the "master" branch:
$ git switch master
After working in the wrong branch, switching to the correct branch would be done using:
$ git switch mytopic
However, your "wrong" branch and correct "mytopic" branch may differ in files that you have modified locally, in which case the above switch would fail like this:
$ git switch mytopic error: You have local changes to 'frotz'; not switching branches.
You can give the -m flag to the command, which would try a three-way merge:
$ git switch -m mytopic Auto-merging frotz
After this three-way merge, the local modifications are not registered in your index file, so git diff would show you what changes you made since the tip of the new branch.
To switch back to the previous branch before we switched to mytopic (i.e. "master" branch):
$ git switch -
You can grow a new branch from any commit. For example, switch to "HEAD~3" and create branch "fixup":
$ git switch -c fixup HEAD~3 Switched to a new branch 'fixup'
If you want to start a new branch from a remote branch of the same name:
$ git switch new-topic Branch `new-topic` set up to track remote branch `new-topic` from `origin` Switched to a new branch `new-topic`
To check out commit HEAD~3 for temporary inspection or experiment without creating a new branch:
$ git switch --detach HEAD~3 HEAD is now at 9fc9555312 Merge branch 'cc/shared-index-permbits'
If it turns out whatever you have done is worth keeping, you can always create a new name for it (without switching away):
$ git switch -c good-surprises
Everything below this line in this section is selectively included from the the section called “git-config(1)” documentation. The content is the same as what's found there:
When you run git checkout <something> or git switch <something> and only have one remote, it may implicitly fall back on checking out and tracking e.g. origin/<something>. This stops working as soon as you have more than one remote with a <something> reference. This setting allows for setting the name of a preferred remote that should always win when it comes to disambiguation. The typical use-case is to set this to origin.
Currently this is used by the section called “git-switch(1)” and the section called “git-checkout(1)” when git checkout <something> or git switch <something> will checkout the <something> branch on another remote, and by the section called “git-worktree(1)” when git worktree add refers to a remote branch. This setting might be used for other checkout-like commands or functionality in the future.
The number of parallel workers to use when updating the working tree. The default is one, i.e. sequential execution. If set to a value less than one, Git will use as many workers as the number of logical cores available. This setting and checkout.thresholdForParallelism affect all commands that perform checkout. E.g. checkout, clone, reset, sparse-checkout, etc.
Parallel checkout usually delivers better performance for repositories located on SSDs or over NFS. For repositories on spinning disks and/or machines with a small number of cores, the default sequential checkout often performs better. The size and compression level of a repository might also influence how well the parallel version performs.
Part of the the section called “git(1)” suite
git submodule [--quiet] [--cached]
git submodule [--quiet] add [<options>] [--] <repository> [<path>]
git submodule [--quiet] status [--cached] [--recursive] [--] [<path>…]
git submodule [--quiet] init [--] [<path>…]
git submodule [--quiet] deinit [-f|--force] (--all|[--] <path>…)
git submodule [--quiet] update [<options>] [--] [<path>…]
git submodule [--quiet] set-branch [<options>] [--] <path>
git submodule [--quiet] set-url [--] <path> <newurl>
git submodule [--quiet] summary [<options>] [--] [<path>…]
git submodule [--quiet] foreach [--recursive] <command>
git submodule [--quiet] sync [--recursive] [--] [<path>…]
git submodule [--quiet] absorbgitdirs [--] [<path>…]
Inspects, updates and manages submodules.
For more information about submodules, see the section called “gitsubmodules(7)”.
With no arguments, shows the status of existing submodules. Several subcommands are available to perform operations on the submodules.
Add the given repository as a submodule at the given path to the changeset to be committed next to the current project: the current project is termed the "superproject".
<repository> is the URL of the new submodule's origin repository. This may be either an absolute URL, or (if it begins with ./ or ../), the location relative to the superproject's default remote repository (Please note that to specify a repository foo.git which is located right next to a superproject bar.git, you'll have to use ../foo.git instead of ./foo.git - as one might expect when following the rules for relative URLs - because the evaluation of relative URLs in Git is identical to that of relative directories).
The default remote is the remote of the remote-tracking branch of the current branch. If no such remote-tracking branch exists or the HEAD is detached, "origin" is assumed to be the default remote. If the superproject doesn't have a default remote configured the superproject is its own authoritative upstream and the current working directory is used instead.
The optional argument <path> is the relative location for the cloned submodule to exist in the superproject. If <path> is not given, the canonical part of the source repository is used ("repo" for "/path/to/repo.git" and "foo" for "host.xz:foo/.git"). If <path> exists and is already a valid Git repository, then it is staged for commit without cloning. The <path> is also used as the submodule's logical name in its configuration entries unless --name is used to specify a logical name.
The given URL is recorded into .gitmodules for use by subsequent users cloning the superproject. If the URL is given relative to the superproject's repository, the presumption is the superproject and submodule repositories will be kept together in the same relative location, and only the superproject's URL needs to be provided. git-submodule will correctly locate the submodule using the relative URL in .gitmodules.
If --ref-format <format> is specified, the ref storage format of newly cloned submodules will be set accordingly.
Show the status of the submodules. This will print the SHA-1 of the currently checked out commit for each submodule, along with the submodule path and the output of git describe for the SHA-1. Each SHA-1 will possibly be prefixed with - if the submodule is not initialized, + if the currently checked out submodule commit does not match the SHA-1 found in the index of the containing repository and U if the submodule has merge conflicts.
If --cached is specified, this command will instead print the SHA-1 recorded in the superproject for each submodule.
If --recursive is specified, this command will recurse into nested submodules, and show their status as well.
If you are only interested in changes of the currently initialized submodules with respect to the commit recorded in the index or the HEAD, the section called “git-status(1)” and the section called “git-diff(1)” will provide that information too (and can also report changes to a submodule's work tree).
Initialize the submodules recorded in the index (which were added and committed elsewhere) by setting submodule.$name.url in .git/config, using the same setting from .gitmodules as a template. If the URL is relative, it will be resolved using the default remote. If there is no default remote, the current repository will be assumed to be upstream.
Optional <path> arguments limit which submodules will be initialized. If no path is specified and submodule.active has been configured, submodules configured to be active will be initialized, otherwise all submodules are initialized.
It will also copy the value of submodule.$name.update, if present in the .gitmodules file, to .git/config, but (1) this command does not alter existing information in .git/config, and (2) submodule.$name.update that is set to a custom command is not copied for security reasons.
You can then customize the submodule clone URLs in .git/config for your local setup and proceed to git submodule update; you can also just use git submodule update --init without the explicit init step if you do not intend to customize any submodule locations.
See the add subcommand for the definition of default remote.
Unregister the given submodules, i.e. remove the whole submodule.$name section from .git/config together with their work tree. Further calls to git submodule update, git submodule foreach and git submodule sync will skip any unregistered submodules until they are initialized again, so use this command if you don't want to have a local checkout of the submodule in your working tree anymore.
When the command is run without pathspec, it errors out, instead of deinit-ing everything, to prevent mistakes.
If --force is specified, the submodule's working tree will be removed even if it contains local modifications.
If you really want to remove a submodule from the repository and commit that use the section called “git-rm(1)” instead. See the section called “gitsubmodules(7)” for removal options.
Update the registered submodules to match what the superproject expects by cloning missing submodules, fetching missing commits in submodules and updating the working tree of the submodules. The "updating" can be done in several ways depending on command line options and the value of submodule.<name>.update configuration variable. The command line option takes precedence over the configuration variable. If neither is given, a checkout is performed. (note: what is in .gitmodules file is irrelevant at this point; see git submodule init above for how .gitmodules is used). The update procedures supported both from the command line as well as through the submodule.<name>.update configuration are:
the commit recorded in the superproject will be checked out in the submodule on a detached HEAD.
If --force is specified, the submodule will be checked out (using git checkout --force), even if the commit specified in the index of the containing repository already matches the commit checked out in the submodule.
The following update procedures have additional limitations:
If the submodule is not yet initialized, and you just want to use the setting as stored in .gitmodules, you can automatically initialize the submodule with the --init option.
If --recursive is specified, this command will recurse into the registered submodules, and update any nested submodules within.
If --ref-format <format> is specified, the ref storage format of newly cloned submodules will be set accordingly.
If --filter <filter-spec> is specified, the given partial clone filter will be applied to the submodule. See the section called “git-rev-list(1)” for details on filter specifications.
Show commit summary between the given commit (defaults to HEAD) and working tree/index. For a submodule in question, a series of commits in the submodule between the given super project commit and the index or working tree (switched by --cached) are shown. If the option --files is given, show the series of commits in the submodule between the index of the super project and the working tree of the submodule (this option doesn't allow to use the --cached option or to provide an explicit commit).
Using the --submodule=log option with the section called “git-diff(1)” will provide that information too.
Evaluates an arbitrary shell command in each checked out submodule. The command has access to the variables $name, $sm_path, $displaypath, $sha1 and $toplevel: $name is the name of the relevant submodule section in .gitmodules, $sm_path is the path of the submodule as recorded in the immediate superproject, $displaypath contains the relative path from the current working directory to the submodules root directory, $sha1 is the commit as recorded in the immediate superproject, and $toplevel is the absolute path to the top-level of the immediate superproject. Note that to avoid conflicts with $PATH on Windows, the $path variable is now a deprecated synonym of $sm_path variable. Any submodules defined in the superproject but not checked out are ignored by this command. Unless given --quiet, foreach prints the name of each submodule before evaluating the command. If --recursive is given, submodules are traversed recursively (i.e. the given shell command is evaluated in nested submodules as well). A non-zero return from the command in any submodule causes the processing to terminate. This can be overridden by adding || : to the end of the command.
As an example, the command below will show the path and currently checked out commit for each submodule:
git submodule foreach 'echo $sm_path `git rev-parse HEAD`'
Synchronizes submodules' remote URL configuration setting to the value specified in .gitmodules. It will only affect those submodules which already have a URL entry in .git/config (that is the case when they are initialized or freshly added). This is useful when submodule URLs change upstream and you need to update your local repositories accordingly.
git submodule sync synchronizes all submodules while git submodule sync -- A synchronizes submodule "A" only.
If --recursive is specified, this command will recurse into the registered submodules, and sync any nested submodules within.
If a git directory of a submodule is inside the submodule, move the git directory of the submodule into its superproject's $GIT_DIR/modules path and then connect the git directory and its working directory by setting the core.worktree and adding a .git file pointing to the git directory embedded in the superprojects git directory.
A repository that was cloned independently and later added as a submodule or old setups have the submodules git directory inside the submodule instead of embedded into the superprojects git directory.
This command is recursive by default.
This option is only valid for the update command. Instead of using the superproject's recorded SHA-1 to update the submodule, use the status of the submodule's remote-tracking branch. The remote used is branch's remote (branch.<name>.remote), defaulting to origin. The remote branch used defaults to the remote HEAD, but the branch name may be overridden by setting the submodule.<name>.branch option in either .gitmodules or .git/config (with .git/config taking precedence).
This works for any of the supported update procedures (--checkout, --rebase, etc.). The only change is the source of the target SHA-1. For example, submodule update --remote --merge will merge upstream submodule changes into the submodules, while submodule update --merge will merge superproject gitlink changes into the submodules.
In order to ensure a current tracking branch state, update --remote fetches the submodule's remote repository before calculating the SHA-1. If you don't want to fetch, you should use submodule update --remote --no-fetch.
Use this option to integrate changes from the upstream subproject with your submodule's current HEAD. Alternatively, you can run git pull from the submodule, which is equivalent except for the remote branch name: update --remote uses the default upstream repository and submodule.<name>.branch, while git pull uses the submodule's branch.<name>.merge. Prefer submodule.<name>.branch if you want to distribute the default upstream branch with the superproject and branch.<name>.merge if you want a more native feel while working in the submodule itself.
This option is only valid for add and update commands. These commands sometimes need to clone a remote repository. In this case, this option will be passed to the the section called “git-clone(1)” command.
NOTE: Do not use this option unless you have read the note for the section called “git-clone(1)”'s --reference, --shared, and --dissociate options carefully.
This option is only valid for add and update commands. These commands sometimes need to clone a remote repository. In this case, this option will be passed to the the section called “git-clone(1)” command.
NOTE: see the NOTE for the --reference option.
When initializing submodules, a .gitmodules file in the top-level directory of the containing repository is used to find the url of each submodule. This file should be formatted in the same way as $GIT_DIR/config. The key to each submodule url is "submodule.$name.url". See the section called “gitmodules(5)” for details.
Part of the the section called “git(1)” suite
git svn is a simple conduit for changesets between Subversion and Git. It provides a bidirectional flow of changes between a Subversion and a Git repository.
git svn can track a standard Subversion repository, following the common "trunk/branches/tags" layout, with the --stdlayout option. It can also follow branches and tags in any layout with the -T/-t/-b options (see options to init below, and also the clone command).
Once tracking a Subversion repository (with any of the above methods), the Git repository can be updated from Subversion by the fetch command and Subversion updated from Git by the dcommit command.
Initializes an empty Git repository with additional metadata directories for git svn. The Subversion URL may be specified as a command-line argument, or as full URL arguments to -T/-t/-b. Optionally, the target directory to operate on can be specified as a second argument. Normally this command initializes the current directory.
This allows one to specify a prefix which is prepended to the names of remotes if trunk/branches/tags are specified. The prefix does not automatically include a trailing slash, so be sure you include one in the argument if that is what you want. If --branches/-b is specified, the prefix must include a trailing slash. Setting a prefix (with a trailing slash) is strongly encouraged in any case, as your SVN-tracking refs will then be located at "refs/remotes/$prefix/", which is compatible with Git's own remote-tracking ref layout (refs/remotes/$remote/). Setting a prefix is also useful if you wish to track multiple projects that share a common repository. By default, the prefix is set to origin/.
Before Git v2.0, the default prefix was "" (no prefix). This meant that SVN-tracking refs were put at "refs/remotes/*", which is incompatible with how Git's own remote-tracking refs are organized. If you still want the old default, you can get it by passing --prefix "" on the command line (--prefix="" may not work if your Perl's Getopt::Long is < v2.37).
Fetch unfetched revisions from the Subversion remote we are tracking. The name of the [svn-remote "…"] section in the $GIT_DIR/config file may be specified as an optional command-line argument.
This automatically updates the rev_map if needed (see $GIT_DIR/svn/**/.rev_map.* in the FILES section below for details).
Store Git commit times in the local time zone instead of UTC. This makes git log (even without --date=local) show the same times that svn log would in the local time zone.
This doesn't interfere with interoperating with the Subversion repository you cloned from, but if you wish for your local Git repository to be able to interoperate with someone else's local Git repository, either don't use this option or you should both use it in the same local time zone.
Ignore refs for branches or tags matching the Perl regular expression. A "negative look-ahead assertion" like ^refs/remotes/origin/(?!tags/wanted-tag|wanted-branch).*$ can be used to allow only certain refs.
config key: svn-remote.<name>.ignore-refs
If the ignore-refs configuration key is set, and the command-line option is also given, both regular expressions will be used.
This allows one to specify a Perl regular expression that will cause skipping of all matching paths from checkout from SVN. The --ignore-paths option should match for every fetch (including automatic fetches due to clone, dcommit, rebase, etc) on a given repository.
config key: svn-remote.<name>.ignore-paths
If the ignore-paths configuration key is set, and the command-line option is also given, both regular expressions will be used.
Examples:
--ignore-paths="^doc"
--ignore-paths="^[^/]+/(?:branches|tags)"
This allows one to specify a Perl regular expression that will cause the inclusion of only matching paths from checkout from SVN. The --include-paths option should match for every fetch (including automatic fetches due to clone, dcommit, rebase, etc) on a given repository. --ignore-paths takes precedence over --include-paths.
config key: svn-remote.<name>.include-paths
Runs init and fetch. It will automatically create a directory based on the basename of the URL passed to it; or if a second argument is passed; it will create a directory and work within that. It accepts all arguments that the init and fetch commands accept; with the exception of --fetch-all and --parent. After a repository is cloned, the fetch command will be able to update revisions without affecting the working tree; and the rebase command will be able to update the working tree with the latest changes.
This fetches revisions from the SVN parent of the current HEAD and rebases the current (uncommitted to SVN) work against it.
This works similarly to svn update or git pull except that it preserves linear history with git rebase instead of git merge for ease of dcommitting with git svn.
This accepts all options that git svn fetch and git rebase accept. However, --fetch-all only fetches from the current [svn-remote], and not all [svn-remote] definitions.
Like git rebase; this requires that the working tree be clean and have no uncommitted changes.
This automatically updates the rev_map if needed (see $GIT_DIR/svn/**/.rev_map.* in the FILES section below for details).
Commit each diff from the current branch directly to the SVN repository, and then rebase or reset (depending on whether or not there is a diff between SVN and head). This will create a revision in SVN for each commit in Git.
When an optional Git branch name (or a Git commit object name) is specified as an argument, the subcommand works on the specified branch, not on the current branch.
Use of dcommit is preferred to set-tree (below).
Commit to this SVN URL (the full path). This is intended to allow existing git svn repositories created with one transport method (e.g. svn:// or http:// for anonymous read) to be reused if a user is later given access to an alternate transport method (e.g. svn+ssh:// or https://) for commit.
config key: svn-remote.<name>.commiturl
config key: svn.commiturl (overwrites all svn-remote.<name>.commiturl options)
Note that the SVN URL of the commiturl config key includes the SVN branch. If you rather want to set the commit URL for an entire SVN repository use svn-remote.<name>.pushurl instead.
Using this option for any other purpose (don't ask) is very strongly discouraged.
Add the given merge information during the dcommit (e.g. --mergeinfo="/branches/foo:1-10"). All svn server versions can store this information (as a property), and svn clients starting from version 1.5 can make use of it. To specify merge information from multiple branches, use a single space character between the branches (--mergeinfo="/branches/foo:1-10 /branches/bar:3,5-6,8")
config key: svn.pushmergeinfo
This option will cause git-svn to attempt to automatically populate the svn:mergeinfo property in the SVN repository when possible. Currently, this can only be done when dcommitting non-fast-forward merges where all parents but the first have already been pushed into SVN.
Ask the user to confirm that a patch set should actually be sent to SVN. For each patch, one may answer "yes" (accept this patch), "no" (discard this patch), "all" (accept all patches), or "quit".
git svn dcommit returns immediately if answer is "no" or "quit", without committing anything to SVN.
Create a branch in the SVN repository.
If more than one --branches (or --tags) option was given to the init or clone command, you must provide the location of the branch (or tag) you wish to create in the SVN repository. <path> specifies which path to use to create the branch or tag and should match the pattern on the left-hand side of one of the configured branches or tags refspecs. You can see these refspecs with the commands
git config --get-all svn-remote.<name>.branches git config --get-all svn-remote.<name>.tags
where <name> is the name of the SVN repository as specified by the -R option to init (or "svn" by default).
Use the specified URL to connect to the destination Subversion repository. This is useful in cases where the source SVN repository is read-only. This option overrides configuration property commiturl.
git config --get-all svn-remote.<name>.commiturl
This should make it easy to look up svn log messages when svn users refer to -r/--revision numbers.
The following features from svn log are supported:
New features:
SVN itself only stores times in UTC and nothing else. The regular svn client converts the UTC time to the local time (or based on the TZ= environment). This command has the same behaviour.
Any other arguments are passed directly to git log
Show what revision and author last modified each line of a file. The output of this mode is format-compatible with the output of svn blame by default. Like the SVN blame command, local uncommitted changes in the working tree are ignored; the version of the file in the HEAD revision is annotated. Unknown arguments are passed directly to git blame.
When given an SVN revision number of the form rN, returns the corresponding Git commit hash (this can optionally be followed by a tree-ish to specify which branch should be searched). When given a tree-ish, returns the corresponding SVN revision number.
Commits the diff of two tree-ish arguments from the command-line. This command does not rely on being inside a git svn init-ed repository. This command takes three arguments, (a) the original tree to diff against, (b) the new tree result, (c) the URL of the target Subversion repository. The final argument (URL) may be omitted if you are working from a git svn-aware repository (that has been init-ed with git svn). The -r<revision> option is required for this.
The commit message is supplied either directly with the -m or -F option, or indirectly from the tag or commit when the second tree-ish denotes such an object, or it is requested by invoking an editor (see --edit option below).
Sets the Subversion property given as the first argument, to the value given as the second argument for the file given as the third argument.
Example:
git svn propset svn:keywords "FreeBSD=%H" devel/py-tipper/Makefile
This will set the property svn:keywords to FreeBSD=%H for the file devel/py-tipper/Makefile.
Undoes the effects of fetch back to the specified revision. This allows you to re-fetch an SVN revision. Normally the contents of an SVN revision should never change and reset should not be necessary. However, if SVN permissions change, or if you alter your --ignore-paths option, a fetch may fail with "not found in commit" (file not previously visible) or "checksum mismatch" (missed a modification). If the problem file cannot be ignored forever (with --ignore-paths) the only way to repair the repo is to use reset.
Only the rev_map and refs/remotes/git-svn are changed (see $GIT_DIR/svn/**/.rev_map.* in the FILES section below for details). Follow reset with a fetch and then git reset or git rebase to move local branches onto the new tree.
Assume you have local changes in "master", but you need to refetch "r2".
r1---r2---r3 remotes/git-svn
\
A---B masterFix the ignore-paths or SVN permissions problem that caused "r2" to be incomplete in the first place. Then:
git svn reset -r2 -p
git svn fetch
r1---r2'--r3' remotes/git-svn
\
r2---r3---A---B masterThen fixup "master" with git rebase. Do NOT use git merge or your history will not be compatible with a future dcommit!
git rebase --onto remotes/git-svn A^ master
r1---r2'--r3' remotes/git-svn
\
A'--B' masterUsed with the fetch command.
This allows revision ranges for partial/cauterized history to be supported. $NUMBER, $NUMBER1:$NUMBER2 (numeric ranges), $NUMBER:HEAD, and BASE:$NUMBER are all supported.
This can allow you to make partial mirrors when running fetch; but is generally not recommended because history will be skipped and lost.
Only used with the set-tree command.
Read a list of commits from stdin and commit them in reverse order. Only the leading sha1 is read from each line, so git rev-list --pretty=oneline output can be used.
Only used with the dcommit, set-tree and commit-diff commands.
Remove directories from the SVN tree if there are no files left behind. SVN can version empty directories, and they are not removed by default if there are no files left in them. Git cannot version empty directories. Enabling this flag will make the commit to SVN act like Git.
config key: svn.rmdir
Only used with the dcommit, set-tree and commit-diff commands.
Edit the commit message before committing to SVN. This is off by default for objects that are commits, and forced on when committing tree objects.
config key: svn.edit
Only used with the dcommit, set-tree and commit-diff commands.
They are both passed directly to git diff-tree; see the section called “git-diff-tree(1)” for more information.
config key: svn.l
config key: svn.findcopiesharder
Syntax is compatible with the file used by git cvsimport but an empty email address can be supplied with <>:
loginname = Joe User <user@example.com>
If this option is specified and git svn encounters an SVN committer name that does not exist in the authors-file, git svn will abort operation. The user will then have to add the appropriate entry. Re-running the previous git svn command after the authors-file is modified should continue operation.
config key: svn.authorsfile
If this option is specified, for each SVN committer name that does not exist in the authors file, the given file is executed with the committer name as the first argument. The program is expected to return a single line of the form "Name <email>" or "Name <>", which will be treated as if included in the authors file.
Due to historical reasons a relative filename is first searched relative to the current directory for init and clone and relative to the root of the working tree for fetch. If filename is not found, it is searched like any other command in $PATH.
config key: svn.authorsProg
These are only used with the dcommit and rebase commands.
Passed directly to git rebase when using dcommit if a git reset cannot be used (see dcommit).
This can be used with the dcommit, rebase, branch and tag commands.
For dcommit, print out the series of Git arguments that would show which diffs would be committed to SVN.
For rebase, display the local branch associated with the upstream svn repository associated with the current branch and the URL of svn repository that will be fetched from.
For branch and tag, display the urls that will be used for copying when creating the branch or tag.
When retrieving svn commits into Git (as part of fetch, rebase, or dcommit operations), look for the first From: line or Signed-off-by trailer in the log message and use that as the author string.
config key: svn.useLogAuthor
When committing to svn from Git (as part of set-tree or dcommit operations), if the existing log message doesn't already have a From: or Signed-off-by trailer, append a From: line based on the Git commit's author string. If you use this, then --use-log-author will retrieve a valid author string for all commits.
config key: svn.addAuthorFrom
This option is only relevant if we are tracking branches (using one of the repository layout options --trunk, --tags, --branches, --stdlayout). For each tracked branch, try to find out where its revision was copied from, and set a suitable parent in the first Git commit for the branch. This is especially helpful when we're tracking a directory that has been moved around within the repository. If this feature is disabled, the branches created by git svn will all be linear and not share any history, meaning that there will be no information on where branches were branched off or merged. However, following long/convoluted histories can take a long time, so disabling this feature may speed up the cloning process. This feature is enabled by default, use --no-follow-parent to disable it.
config key: svn.followparent
This gets rid of the git-svn-id: lines at the end of every commit.
This option can only be used for one-shot imports as git svn will not be able to fetch again without metadata. Additionally, if you lose your $GIT_DIR/svn/**/.rev_map.* files, git svn will not be able to rebuild them.
The git svn log command will not work on repositories using this, either. Using this conflicts with the useSvmProps option for (hopefully) obvious reasons.
This option is NOT recommended as it makes it difficult to track down old references to SVN revision numbers in existing documentation, bug reports, and archives. If you plan to eventually migrate from SVN to Git and are certain about dropping SVN history, consider git-filter-repo instead. filter-repo also allows reformatting of metadata for ease-of-reading and rewriting authorship info for non-"svn.authorsFile" users.
This allows git svn to re-map repository URLs and UUIDs from mirrors created using SVN::Mirror (or svk) for metadata.
If an SVN revision has a property, "svm:headrev", it is likely that the revision was created by SVN::Mirror (also used by SVK). The property contains a repository UUID and a revision. We want to make it look like we are mirroring the original URL, so introduce a helper function that returns the original identity URL and UUID, and use it when generating metadata in commit messages.
Since the noMetadata, rewriteRoot, rewriteUUID, useSvnsyncProps and useSvmProps options all affect the metadata generated and used by git svn; they must be set in the configuration file before any history is imported and these settings should never be changed once they are set.
Additionally, only one of these options can be used per svn-remote section because they affect the git-svn-id: metadata line, except for rewriteRoot and rewriteUUID which can be used together.
Tracking and contributing to the trunk of a Subversion-managed project (ignoring tags and branches):
# Clone a repo (like git clone):
git svn clone http://svn.example.com/project/trunk
# Enter the newly cloned directory:
cd trunk
# You should be on master branch, double-check with 'git branch'
git branch
# Do some work and commit locally to Git:
git commit ...
# Something is committed to SVN, rebase your local changes against the
# latest changes in SVN:
git svn rebase
# Now commit your changes (that were committed previously using Git) to SVN,
# as well as automatically updating your working HEAD:
git svn dcommit
# Append svn:ignore and svn:global-ignores settings to the default Git exclude file:
git svn show-ignore >> .git/info/excludeTracking and contributing to an entire Subversion-managed project (complete with a trunk, tags and branches):
# Clone a repo with standard SVN directory layout (like git clone):
git svn clone http://svn.example.com/project --stdlayout --prefix svn/
# Or, if the repo uses a non-standard directory layout:
git svn clone http://svn.example.com/project -T tr -b branch -t tag --prefix svn/
# View all branches and tags you have cloned:
git branch -r
# Create a new branch in SVN
git svn branch waldo
# Reset your master to trunk (or any other branch, replacing 'trunk'
# with the appropriate name):
git reset --hard svn/trunk
# You may only dcommit to one branch/tag/trunk at a time. The usage
# of dcommit/rebase/show-ignore should be the same as above.The initial git svn clone can be quite time-consuming (especially for large Subversion repositories). If multiple people (or one person with multiple machines) want to use git svn to interact with the same Subversion repository, you can do the initial git svn clone to a repository on a server and have each person clone that repository with git clone:
# Do the initial import on a server
ssh server "cd /pub && git svn clone http://svn.example.com/project [options...]"
# Clone locally - make sure the refs/remotes/ space matches the server
mkdir project
cd project
git init
git remote add origin server:/pub/project
git config --replace-all remote.origin.fetch '+refs/remotes/*:refs/remotes/*'
git fetch
# Prevent fetch/pull from remote Git server in the future,
# we only want to use git svn for future updates
git config --remove-section remote.origin
# Create a local branch from one of the branches just fetched
git checkout -b master FETCH_HEAD
# Initialize 'git svn' locally (be sure to use the same URL and
# --stdlayout/-T/-b/-t/--prefix options as were used on server)
git svn init http://svn.example.com/project [options...]
# Pull the latest changes from Subversion
git svn rebasePrefer to use git svn rebase or git rebase, rather than git pull or git merge to synchronize unintegrated commits with a git svn branch. Doing so will keep the history of unintegrated commits linear with respect to the upstream SVN repository and allow the use of the preferred git svn dcommit subcommand to push unintegrated commits back into SVN.
Originally, git svn recommended that developers pulled or merged from the git svn branch. This was because the author favored git svn set-tree B to commit a single head rather than the git svn set-tree A..B notation to commit multiple commits. Use of git pull or git merge with git svn set-tree A..B will cause non-linear history to be flattened when committing into SVN and this can lead to merge commits unexpectedly reversing previous commits in SVN.
While git svn can track copy history (including branches and tags) for repositories adopting a standard layout, it cannot yet represent merge history that happened inside git back upstream to SVN users. Therefore it is advised that users keep history as linear as possible inside Git to ease compatibility with SVN (see the CAVEATS section below).
If git svn is configured to fetch branches (and --follow-branches is in effect), it sometimes creates multiple Git branches for one SVN branch, where the additional branches have names of the form branchname@nnn (with nnn an SVN revision number). These additional branches are created if git svn cannot find a parent commit for the first commit in an SVN branch, to connect the branch to the history of the other branches.
Normally, the first commit in an SVN branch consists of a copy operation. git svn will read this commit to get the SVN revision the branch was created from. It will then try to find the Git commit that corresponds to this SVN revision, and use that as the parent of the branch. However, it is possible that there is no suitable Git commit to serve as parent. This will happen, among other reasons, if the SVN branch is a copy of a revision that was not fetched by git svn (e.g. because it is an old revision that was skipped with --revision), or if in SVN a directory was copied that is not tracked by git svn (such as a branch that is not tracked at all, or a subdirectory of a tracked branch). In these cases, git svn will still create a Git branch, but instead of using an existing Git commit as the parent of the branch, it will read the SVN history of the directory the branch was copied from and create appropriate Git commits. This is indicated by the message "Initializing parent: <branchname>".
Additionally, it will create a special branch named <branchname>@<SVN-Revision>, where <SVN-Revision> is the SVN revision number the branch was copied from. This branch will point to the newly created parent commit of the branch. If in SVN the branch was deleted and later recreated from a different version, there will be multiple such branches with an @.
Note that this may mean that multiple Git commits are created for a single SVN revision.
An example: in an SVN repository with a standard trunk/tags/branches layout, a directory trunk/sub is created in r.100. In r.200, trunk/sub is branched by copying it to branches/. git svn clone -s will then create a branch sub. It will also create new Git commits for r.100 through r.199 and use these as the history of branch sub. Thus there will be two Git commits for each revision from r.100 to r.199 (one containing trunk/, one containing trunk/sub/). Finally, it will create a branch sub@200 pointing to the new parent commit of branch sub (i.e. the commit for r.200 and trunk/sub/).
For the sake of simplicity and interoperating with Subversion, it is recommended that all git svn users clone, fetch and dcommit directly from the SVN server, and avoid all git clone/pull/merge/push operations between Git repositories and branches. The recommended method of exchanging code between Git branches and users is git format-patch and git am, or just 'dcommit'ing to the SVN repository.
Running git merge or git pull is NOT recommended on a branch you plan to dcommit from because Subversion users cannot see any merges you've made. Furthermore, if you merge or pull from a Git branch that is a mirror of an SVN branch, dcommit may commit to the wrong branch.
If you do merge, note the following rule: git svn dcommit will attempt to commit on top of the SVN commit named in
git log --grep=^git-svn-id: --first-parent -1
You must therefore ensure that the most recent commit of the branch you want to dcommit to is the first parent of the merge. Chaos will ensue otherwise, especially if the first parent is an older commit on the same SVN branch.
git clone does not clone branches under the refs/remotes/ hierarchy or any git svn metadata, or config. So repositories created and managed with using git svn should use rsync for cloning, if cloning is to be done at all.
Since dcommit uses rebase internally, any Git branches you git push to before dcommit on will require forcing an overwrite of the existing ref on the remote repository. This is generally considered bad practice, see the the section called “git-push(1)” documentation for details.
Do not use the --amend option of the section called “git-commit(1)” on a change you've already dcommitted. It is considered bad practice to --amend commits you've already pushed to a remote repository for other users, and dcommit with SVN is analogous to that.
When cloning an SVN repository, if none of the options for describing the repository layout is used (--trunk, --tags, --branches, --stdlayout), git svn clone will create a Git repository with completely linear history, where branches and tags appear as separate directories in the working copy. While this is the easiest way to get a copy of a complete repository, for projects with many branches it will lead to a working copy many times larger than just the trunk. Thus for projects using the standard directory structure (trunk/branches/tags), it is recommended to clone with option --stdlayout. If the project uses a non-standard structure, and/or if branches and tags are not required, it is easiest to only clone one directory (typically trunk), without giving any repository layout options. If the full history with branches and tags is required, the options --trunk / --branches / --tags must be used.
When using multiple --branches or --tags, git svn does not automatically handle name collisions (for example, if two branches from different paths have the same name, or if a branch and a tag have the same name). In these cases, use init to set up your Git repository then, before your first fetch, edit the $GIT_DIR/config file so that the branches and tags are associated with different name spaces. For example:
branches = stable/*:refs/remotes/svn/stable/* branches = debug/*:refs/remotes/svn/debug/*
git svn stores [svn-remote] configuration information in the repository $GIT_DIR/config file. It is similar the core Git [remote] sections except fetch keys do not accept glob arguments; but they are instead handled by the branches and tags keys. Since some SVN repositories are oddly configured with multiple projects glob expansions such those listed below are allowed:
[svn-remote "project-a"]
url = http://server.org/svn
fetch = trunk/project-a:refs/remotes/project-a/trunk
branches = branches/*/project-a:refs/remotes/project-a/branches/*
branches = branches/release_*:refs/remotes/project-a/branches/release_*
branches = branches/re*se:refs/remotes/project-a/branches/*
tags = tags/*/project-a:refs/remotes/project-a/tags/*Keep in mind that the * (asterisk) wildcard of the local ref (right of the :) must be the farthest right path component; however the remote wildcard may be anywhere as long as it's an independent path component (surrounded by / or EOL). This type of configuration is not automatically created by init and should be manually entered with a text-editor or using git config.
Also note that only one asterisk is allowed per word. For example:
branches = branches/re*se:refs/remotes/project-a/branches/*
will match branches release, rese, re123se, however
branches = branches/re*s*e:refs/remotes/project-a/branches/*
will produce an error.
It is also possible to fetch a subset of branches or tags by using a comma-separated list of names within braces. For example:
[svn-remote "huge-project"]
url = http://server.org/svn
fetch = trunk/src:refs/remotes/trunk
branches = branches/{red,green}/src:refs/remotes/project-a/branches/*
tags = tags/{1.0,2.0}/src:refs/remotes/project-a/tags/*Multiple fetch, branches, and tags keys are supported:
[svn-remote "messy-repo"]
url = http://server.org/svn
fetch = trunk/project-a:refs/remotes/project-a/trunk
fetch = branches/demos/june-project-a-demo:refs/remotes/project-a/demos/june-demo
branches = branches/server/*:refs/remotes/project-a/branches/*
branches = branches/demos/2011/*:refs/remotes/project-a/2011-demos/*
tags = tags/server/*:refs/remotes/project-a/tags/*Creating a branch in such a configuration requires disambiguating which location to use using the -d or --destination flag:
$ git svn branch -d branches/server release-2-3-0
Note that git-svn keeps track of the highest revision in which a branch or tag has appeared. If the subset of branches or tags is changed after fetching, then $GIT_DIR/svn/.metadata must be manually edited to remove (or reset) branches-maxRev and/or tags-maxRev as appropriate.
Mapping between Subversion revision numbers and Git commit names. In a repository where the noMetadata option is not set, this can be rebuilt from the git-svn-id: lines that are at the end of every commit (see the svn.noMetadata section above for details).
git svn fetch and git svn rebase automatically update the rev_map if it is missing or not up to date. git svn reset automatically rewinds it.
We ignore all SVN properties except svn:executable. Any unhandled properties are logged to $GIT_DIR/svn/<refname>/unhandled.log
Renamed and copied directories are not detected by Git and hence not tracked when committing to SVN. I do not plan on adding support for this as it's quite difficult and time-consuming to get working for all the possible corner cases (Git doesn't do it, either). Committing renamed and copied files is fully supported if they're similar enough for Git to detect them.
In SVN, it is possible (though discouraged) to commit changes to a tag (because a tag is just a directory copy, thus technically the same as a branch). When cloning an SVN repository, git svn cannot know if such a commit to a tag will happen in the future. Thus it acts conservatively and imports all SVN tags as branches, prefixing the tag name with tags/.
Part of the the section called “git(1)” suite
git symbolic-ref [-m <reason>] <name> <ref>
git symbolic-ref [-q] [--short] [--no-recurse] <name>
git symbolic-ref --delete [-q] <name>
Given one argument, reads which branch head the given symbolic ref refers to and outputs its path, relative to the .git/ directory. Typically you would give HEAD as the <name> argument to see which branch your working tree is on.
Given two arguments, creates or updates a symbolic ref <name> to point at the given branch <ref>.
Given --delete and an additional argument, deletes the given symbolic ref.
A symbolic ref is a regular file that stores a string that begins with ref: refs/. For example, your .git/HEAD is a regular file whose content is ref: refs/heads/master.
In the past, .git/HEAD was a symbolic link pointing at refs/heads/master. When we wanted to switch to another branch, we did ln -sf refs/heads/newbranch .git/HEAD, and when we wanted to find out which branch we are on, we did readlink .git/HEAD. But symbolic links are not entirely portable, so they are now deprecated and symbolic refs (as described above) are used by default.
git symbolic-ref will exit with status 0 if the contents of the symbolic ref were printed correctly, with status 1 if the requested name is not a symbolic ref, or 128 if another error occurs.
Part of the the section called “git(1)” suite
git tag [-a | -s | -u <key-id>] [-f] [-m <msg> | -F <file>] [-e]
[(--trailer <token>[(=|:)<value>])…]
<tagname> [<commit> | <object>]
git tag -d <tagname>…
git tag [-n[<num>]] -l [--contains <commit>] [--no-contains <commit>]
[--points-at <object>] [--column[=<options>] | --no-column]
[--create-reflog] [--sort=<key>] [--format=<format>]
[--merged <commit>] [--no-merged <commit>] [<pattern>…]
git tag -v [--format=<format>] <tagname>…
Add a tag reference in refs/tags/, unless -d/-l/-v is given to delete, list or verify tags.
Unless -f is given, the named tag must not yet exist.
If one of -a, -s, or -u <key-id> is passed, the command creates a tag object, and requires a tag message. Unless -m <msg> or -F <file> is given, an editor is started for the user to type in the tag message.
If -m <msg> or -F <file> or --trailer <token>[=<value>] is given and -a, -s, and -u <key-id> are absent, -a is implied.
Otherwise, a tag reference that points directly at the given object (i.e., a lightweight tag) is created.
A GnuPG signed tag object will be created when -s or -u <key-id> is used. When -u <key-id> is not used, the committer identity for the current user is used to find the GnuPG key for signing. The configuration variable gpg.program is used to specify custom GnuPG binary.
Tag objects (created with -a, -s, or -u) are called "annotated" tags; they contain a creation date, the tagger name and e-mail, a tagging message, and an optional GnuPG signature. Whereas a "lightweight" tag is simply a name for an object (usually a commit object).
Annotated tags are meant for release while lightweight tags are meant for private or temporary object labels. For this reason, some git commands for naming objects (like git describe) will ignore lightweight tags by default.
<num> specifies how many lines from the annotation, if any, are printed when using -l. Implies --list.
The default is not to print any annotation lines. If no number is given to -n, only the first line is printed. If the tag is not annotated, the commit message is displayed instead.
List tags. With optional <pattern>..., e.g. git tag --list 'v-*', list only the tags that match the pattern(s).
Running "git tag" without arguments also lists all tags. The pattern is a shell wildcard (i.e., matched using fnmatch(3)). Multiple patterns may be given; if any of them matches, the tag is shown.
This option is implicitly supplied if any other list-like option such as --contains is provided. See the documentation for each of those options for details.
Display tag listing in columns. See configuration variable column.tag for option syntax. --column and --no-column without options are equivalent to always and never respectively.
This option is only applicable when listing tags without annotation lines.
By default, git tag in sign-with-default mode (-s) will use your committer identity (of the form Your Name <your@email.address>) to find a key. If you want to use a different default key, you can specify it in the repository configuration as follows:
[user]
signingKey = <gpg-key-id>pager.tag is only respected when listing tags, i.e., when -l is used or implied. The default is to use a pager. See the section called “git-config(1)”.
What should you do when you tag a wrong commit and you would want to re-tag?
If you never pushed anything out, just re-tag it. Use "-f" to replace the old one. And you're done.
But if you have pushed things out (or others could just read your repository directly), then others will have already seen the old tag. In that case you can do one of two things:
However, Git does not (and it should not) change tags behind users back. So if somebody already got the old tag, doing a git pull on your tree shouldn't just make them overwrite the old one.
If somebody got a release tag from you, you cannot just change the tag for them by updating your own one. This is a big security issue, in that people MUST be able to trust their tag-names. If you really want to do the insane thing, you need to just fess up to it, and tell people that you messed up. You can do that by making a very public announcement saying:
Ok, I messed up, and I pushed out an earlier version tagged as X. I
then fixed something, and retagged the *fixed* tree as X again.
If you got the wrong tag, and want the new one, please delete
the old one and fetch the new one by doing:
git tag -d X
git fetch origin tag X
to get my updated tag.
You can test which tag you have by doing
git rev-parse X
which should return 0123456789abcdef.. if you have the new version.
Sorry for the inconvenience.Does this seem a bit complicated? It should be. There is no way that it would be correct to just "fix" it automatically. People need to know that their tags might have been changed.
If you are following somebody else's tree, you are most likely using remote-tracking branches (eg. refs/remotes/origin/master). You usually want the tags from the other end.
On the other hand, if you are fetching because you would want a one-shot merge from somebody else, you typically do not want to get tags from there. This happens more often for people near the toplevel but not limited to them. Mere mortals when pulling from each other do not necessarily want to automatically get private anchor point tags from the other person.
Often, "please pull" messages on the mailing list just provide two pieces of information: a repo URL and a branch name; this is designed to be easily cut&pasted at the end of a git fetch command line:
Linus, please pull from
git://git..../proj.git master
to get the following updates...becomes:
$ git pull git://git..../proj.git master
In such a case, you do not want to automatically follow the other person's tags.
One important aspect of Git is its distributed nature, which largely means there is no inherent "upstream" or "downstream" in the system. On the face of it, the above example might seem to indicate that the tag namespace is owned by the upper echelon of people and that tags only flow downwards, but that is not the case. It only shows that the usage pattern determines who are interested in whose tags.
A one-shot pull is a sign that a commit history is now crossing the boundary between one circle of people (e.g. "people who are primarily interested in the networking part of the kernel") who may have their own set of tags (e.g. "this is the third release candidate from the networking group to be proposed for general consumption with 2.6.21 release") to another circle of people (e.g. "people who integrate various subsystem improvements"). The latter are usually not interested in the detailed tags used internally in the former group (that is what "internal" means). That is why it is desirable not to follow tags automatically in this case.
It may well be that among networking people, they may want to exchange the tags internal to their group, but in that workflow they are most likely tracking each other's progress by having remote-tracking branches. Again, the heuristic to automatically follow such tags is a good thing.
If you have imported some changes from another VCS and would like to add tags for major releases of your work, it is useful to be able to specify the date to embed inside of the tag object; such data in the tag object affects, for example, the ordering of tags in the gitweb interface.
To set the date used in future tag objects, set the environment variable GIT_COMMITTER_DATE (see the later discussion of possible values; the most common form is "YYYY-MM-DD HH:MM").
For example:
$ GIT_COMMITTER_DATE="2006-10-02 10:31" git tag -s v1.0.1
The GIT_AUTHOR_DATE and GIT_COMMITTER_DATE environment variables support the following date formats:
Time and date specified by the ISO 8601 standard, for example 2005-04-07T22:13:13. The parser accepts a space instead of the T character as well. Fractional parts of a second will be ignored, for example 2005-04-07T22:13:13.019 will be treated as 2005-04-07T22:13:13.
In addition, the date part is accepted in the following formats: YYYY.MM.DD, MM/DD/YYYY and DD.MM.YYYY.
When combining multiple --contains and --no-contains filters, only references that contain at least one of the --contains commits and contain none of the --no-contains commits are shown.
When combining multiple --merged and --no-merged filters, only references that are reachable from at least one of the --merged commits and from none of the --no-merged commits are shown.
Part of the the section called “git(1)” suite
Creates a file holding the contents of the blob specified by sha1. It returns the name of the temporary file in the following format: .merge_file_XXXXX
Part of the the section called “git(1)” suite
Read a packed archive (.pack) from the standard input, expanding the objects contained within and writing them into the repository in "loose" (one object per file) format.
Objects that already exist in the repository will not be unpacked from the packfile. Therefore, nothing will be unpacked if you use this command on a packfile that exists within the target repository.
See the section called “git-repack(1)” for options to generate new packs and replace existing ones.
Part of the the section called “git(1)” suite
git update-index
[--add] [--remove | --force-remove] [--replace]
[--refresh] [-q] [--unmerged] [--ignore-missing]
[(--cacheinfo <mode>,<object>,<file>)…]
[--chmod=(+|-)x]
[--[no-]assume-unchanged]
[--[no-]skip-worktree]
[--[no-]ignore-skip-worktree-entries]
[--[no-]fsmonitor-valid]
[--ignore-submodules]
[--[no-]split-index]
[--[no-|test-|force-]untracked-cache]
[--[no-]fsmonitor]
[--really-refresh] [--unresolve] [--again | -g]
[--info-only] [--index-info]
[-z] [--stdin] [--index-version <n>]
[--show-index-version]
[--verbose]
[--] [<file>…]
Modifies the index. Each file mentioned is updated into the index and any unmerged or needs updating state is cleared.
See also the section called “git-add(1)” for a more user-friendly way to do some of the most common operations on the index.
The way git update-index handles files it is told about can be modified using the various options:
When this flag is specified, the object names recorded for the paths are not updated. Instead, this option sets/unsets the "assume unchanged" bit for the paths. When the "assume unchanged" bit is on, the user promises not to change the file and allows Git to assume that the working tree file matches what is recorded in the index. If you want to change the working tree file, you need to unset the bit to tell Git. This is sometimes helpful when working with a big project on a filesystem that has a very slow lstat(2) system call (e.g. cifs).
Git will fail (gracefully) in case it needs to modify this file in the index e.g. when merging in a commit; thus, in case the assumed-untracked file is changed upstream, you will need to handle the situation manually.
Write the resulting index out in the named on-disk format version. Supported versions are 2, 3, and 4. The current default version is 2 or 3, depending on whether extra features are used, such as git add -N. With --verbose, also report the version the index file uses before and after this command.
Version 4 performs a simple pathname compression that reduces index size by 30%-50% on large repositories, which results in faster load time. Git supports it since version 1.8.0, released in October 2012, and support for it was added to libgit2 in 2016 and to JGit in 2020. Older versions of this manual page called it "relatively young", but it should be considered mature technology these days.
Enable or disable split index mode. If split-index mode is already enabled and --split-index is given again, all changes in $GIT_DIR/index are pushed back to the shared index file.
These options take effect whatever the value of the core.splitIndex configuration variable (see the section called “git-config(1)”). But a warning is emitted when the change goes against the configured value, as the configured value will take effect next time the index is read and this will remove the intended effect of the option.
Enable or disable untracked cache feature. Please use --test-untracked-cache before enabling it.
These options take effect whatever the value of the core.untrackedCache configuration variable (see the section called “git-config(1)”). But a warning is emitted when the change goes against the configured value, as the configured value will take effect next time the index is read and this will remove the intended effect of the option.
--refresh does not calculate a new sha1 file or bring the index up to date for mode/content changes. But what it does do is to "re-match" the stat information of a file with the index, so that you can refresh the index for a file that hasn't been changed but where the stat entry is out of date.
For example, you'd want to do this after doing a git read-tree, to link up the stat index details with the proper files.
--cacheinfo is used to register a file that is not in the current working directory. This is useful for minimum-checkout merging.
To pretend you have a file at path with mode and sha1, say:
$ git update-index --add --cacheinfo <mode>,<sha1>,<path>
--info-only is used to register files without placing them in the object database. This is useful for status-only repositories.
Both --cacheinfo and --info-only behave similarly: the index is updated but the object database isn't. --cacheinfo is useful when the object is in the database but the file isn't available locally. --info-only is useful when the file is available, but you do not wish to update the object database.
--index-info is a more powerful mechanism that lets you feed multiple entry definitions from the standard input, and designed specifically for scripts. It can take inputs of three formats:
mode SP type SP sha1 TAB path
This format is to stuff git ls-tree output into the index.
mode SP sha1 SP stage TAB path
This format is to put higher order stages into the index file and matches git ls-files --stage output.
mode SP sha1 TAB path
This format is no longer produced by any Git command, but is and will continue to be supported by update-index --index-info.
To place a higher stage entry to the index, the path should first be removed by feeding a mode=0 entry for the path, and then feeding necessary input lines in the third format.
For example, starting with this index:
$ git ls-files -s 100644 8a1218a1024a212bb3db30becd860315f9f3ac52 0 frotz
you can feed the following input to --index-info:
$ git update-index --index-info 0 0000000000000000000000000000000000000000 frotz 100644 8a1218a1024a212bb3db30becd860315f9f3ac52 1 frotz 100755 8a1218a1024a212bb3db30becd860315f9f3ac52 2 frotz
The first line of the input feeds 0 as the mode to remove the path; the SHA-1 does not matter as long as it is well formatted. Then the second and third line feeds stage 1 and stage 2 entries for that path. After the above, we would end up with this:
$ git ls-files -s 100644 8a1218a1024a212bb3db30becd860315f9f3ac52 1 frotz 100755 8a1218a1024a212bb3db30becd860315f9f3ac52 2 frotz
Many operations in Git depend on your filesystem to have an efficient lstat(2) implementation, so that st_mtime information for working tree files can be cheaply checked to see if the file contents have changed from the version recorded in the index file. Unfortunately, some filesystems have inefficient lstat(2). If your filesystem is one of them, you can set "assume unchanged" bit to paths you have not changed to cause Git not to do this check. Note that setting this bit on a path does not mean Git will check the contents of the file to see if it has changed -- it makes Git to omit any checking and assume it has not changed. When you make changes to working tree files, you have to explicitly tell Git about it by dropping "assume unchanged" bit, either before or after you modify them.
In order to set "assume unchanged" bit, use --assume-unchanged option. To unset, use --no-assume-unchanged. To see which files have the "assume unchanged" bit set, use git ls-files -v (see the section called “git-ls-files(1)”).
The command looks at core.ignorestat configuration variable. When this is true, paths updated with git update-index paths... and paths updated with other Git commands that update both index and working tree (e.g. git apply --index, git checkout-index -u, and git read-tree -u) are automatically marked as "assume unchanged". Note that "assume unchanged" bit is not set if git update-index --refresh finds the working tree file matches the index (use git update-index --really-refresh if you want to mark them as "assume unchanged").
Sometimes users confuse the assume-unchanged bit with the skip-worktree bit. See the final paragraph in the "Skip-worktree bit" section below for an explanation of the differences.
To update and refresh only the files already checked out:
$ git checkout-index -n -f -a && git update-index --ignore-missing --refresh
$ git update-index --really-refresh$ git update-index --no-assume-unchanged foo.c
$ git diff --name-only
$ edit foo.c $ git diff --name-only
M foo.c $ git update-index foo.c
$ git diff --name-only
$ edit foo.c $ git diff --name-only
$ git update-index --no-assume-unchanged foo.c
$ git diff --name-only
M foo.c
forces lstat(2) to set "assume unchanged" bits for paths that match index. | |
mark the path to be edited. | |
this does lstat(2) and finds index matches the path. | |
this does lstat(2) and finds index does not match the path. | |
registering the new version to index sets "assume unchanged" bit. | |
and it is assumed unchanged. | |
even after you edit it. | |
you can tell about the change after the fact. | |
now it checks with lstat(2) and finds it has been changed. |
Skip-worktree bit can be defined in one (long) sentence: Tell git to avoid writing the file to the working directory when reasonably possible, and treat the file as unchanged when it is not present in the working directory.
Note that not all git commands will pay attention to this bit, and some only partially support it.
The update-index flags and the read-tree capabilities relating to the skip-worktree bit predated the introduction of the the section called “git-sparse-checkout(1)” command, which provides a much easier way to configure and handle the skip-worktree bits. If you want to reduce your working tree to only deal with a subset of the files in the repository, we strongly encourage the use of the section called “git-sparse-checkout(1)” in preference to the low-level update-index and read-tree primitives.
The primary purpose of the skip-worktree bit is to enable sparse checkouts, i.e. to have working directories with only a subset of paths present. When the skip-worktree bit is set, Git commands (such as switch, pull, merge) will avoid writing these files. However, these commands will sometimes write these files anyway in important cases such as conflicts during a merge or rebase. Git commands will also avoid treating the lack of such files as an intentional deletion; for example git add -u will not stage a deletion for these files and git commit -a will not make a commit deleting them either.
Although this bit looks similar to assume-unchanged bit, its goal is different. The assume-unchanged bit is for leaving the file in the working tree but having Git omit checking it for changes and presuming that the file has not been changed (though if it can determine without stat'ing the file that it has changed, it is free to record the changes). skip-worktree tells Git to ignore the absence of the file, avoid updating it when possible with commands that normally update much of the working directory (e.g. checkout, switch, pull, etc.), and not have its absence be recorded in commits. Note that in sparse checkouts (setup by git sparse-checkout or by configuring core.sparseCheckout to true), if a file is marked as skip-worktree in the index but is found in the working tree, Git will clear the skip-worktree bit for that file.
This mode is designed for repositories with very large indexes, and aims at reducing the time it takes to repeatedly write these indexes.
In this mode, the index is split into two files, $GIT_DIR/index and $GIT_DIR/sharedindex.<SHA-1>. Changes are accumulated in $GIT_DIR/index, the split index, while the shared index file contains all index entries and stays unchanged.
All changes in the split index are pushed back to the shared index file when the number of entries in the split index reaches a level specified by the splitIndex.maxPercentChange config variable (see the section called “git-config(1)”).
Each time a new shared index file is created, the old shared index files are deleted if their modification time is older than what is specified by the splitIndex.sharedIndexExpire config variable (see the section called “git-config(1)”).
To avoid deleting a shared index file that is still used, its modification time is updated to the current time every time a new split index based on the shared index file is either created or read from.
This cache is meant to speed up commands that involve determining untracked files such as git status.
This feature works by recording the mtime of the working tree directories and then omitting reading directories and stat calls against files in those directories whose mtime hasn't changed. For this to work the underlying operating system and file system must change the st_mtime field of directories if files in the directory are added, modified or deleted.
You can test whether the filesystem supports that with the --test-untracked-cache option. The --untracked-cache option used to implicitly perform that test in older versions of Git, but that's no longer the case.
If you want to enable (or disable) this feature, it is easier to use the core.untrackedCache configuration variable (see the section called “git-config(1)”) than using the --untracked-cache option to git update-index in each repository, especially if you want to do so across all repositories you use, because you can set the configuration variable to true (or false) in your $HOME/.gitconfig just once and have it affect all repositories you touch.
When the core.untrackedCache configuration variable is changed, the untracked cache is added to or removed from the index the next time a command reads the index; while when --[no-|force-]untracked-cache are used, the untracked cache is immediately added to or removed from the index.
Before 2.17, the untracked cache had a bug where replacing a directory with a symlink to another directory could cause it to incorrectly show files tracked by git as untracked. See the "status: add a failing test showing a core.untrackedCache bug" commit to git.git. A workaround for that is (and this might work for other undiscovered bugs in the future):
$ git -c core.untrackedCache=false status
This bug has also been shown to affect non-symlink cases of replacing a directory with a file when it comes to the internal structures of the untracked cache, but no case has been reported where this resulted in wrong "git status" output.
There are also cases where existing indexes written by git versions before 2.17 will reference directories that don't exist anymore, potentially causing many "could not open directory" warnings to be printed on "git status". These are new warnings for existing issues that were previously silently discarded.
As with the bug described above the solution is to one-off do a "git status" run with core.untrackedCache=false to flush out the leftover bad data.
This feature is intended to speed up git operations for repos that have large working directories.
It enables git to work together with a file system monitor (see the section called “git-fsmonitor--daemon(1)” and the "fsmonitor-watchman" section of the section called “githooks(5)”) that can inform it as to what files have been modified. This enables git to avoid having to lstat() every file to find modified files.
When used in conjunction with the untracked cache, it can further improve performance by avoiding the cost of scanning the entire working directory looking for new files.
If you want to enable (or disable) this feature, it is easier to use the core.fsmonitor configuration variable (see the section called “git-config(1)”) than using the --fsmonitor option to git update-index in each repository, especially if you want to do so across all repositories you use, because you can set the configuration variable in your $HOME/.gitconfig just once and have it affect all repositories you touch.
When the core.fsmonitor configuration variable is changed, the file system monitor is added to or removed from the index the next time a command reads the index. When --[no-]fsmonitor are used, the file system monitor is immediately added to or removed from the index.
The command honors core.filemode configuration variable. If your repository is on a filesystem whose executable bits are unreliable, this should be set to false (see the section called “git-config(1)”). This causes the command to ignore differences in file modes recorded in the index and the file mode on the filesystem if they differ only on executable bit. On such an unfortunate filesystem, you may need to use git update-index --chmod=.
Quite similarly, if core.symlinks configuration variable is set to false (see the section called “git-config(1)”), symbolic links are checked out as plain files, and this command does not modify a recorded file mode from symbolic link to regular file.
The command looks at core.ignorestat configuration variable. See Using "assume unchanged" bit section above.
The command also looks at core.trustctime configuration variable. It can be useful when the inode change time is regularly modified by something outside Git (file system crawlers and backup systems use ctime for marking files processed) (see the section called “git-config(1)”).
The untracked cache extension can be enabled by the core.untrackedCache configuration variable (see the section called “git-config(1)”).
Users often try to use the assume-unchanged and skip-worktree bits to tell Git to ignore changes to files that are tracked. This does not work as expected, since Git may still check working tree files against the index when performing certain operations. In general, Git does not provide a way to ignore changes to tracked files, so alternate solutions are recommended.
For example, if the file you want to change is some sort of config file, the repository can include a sample config file that can then be copied into the ignored name and modified. The repository can even include a script to treat the sample file as a template, modifying and copying it automatically.
the section called “git-config(1)”, the section called “git-add(1)”, the section called “git-ls-files(1)”
Part of the the section called “git(1)” suite
gitupdate-ref[-m<reason>] [--no-deref]-d<ref> [<old-oid>]
gitupdate-ref[-m<reason>] [--no-deref] [--create-reflog] <ref> <new-oid> [<old-oid>]
gitupdate-ref[-m<reason>] [--no-deref]--stdin[-z] [--batch-updates]
Given two arguments, stores the <new-oid> in the <ref>, possibly dereferencing the symbolic refs. E.g. git update-ref HEAD <new-oid> updates the current branch head to the new object.
Given three arguments, stores the <new-oid> in the <ref>, possibly dereferencing the symbolic refs, after verifying that the current value of the <ref> matches <old-oid>. E.g. git update-ref refs/heads/master <new-oid> <old-oid> updates the master branch head to <new-oid> only if its current value is <old-oid>. You can specify 40 "0" or an empty string as <old-oid> to make sure that the ref you are creating does not exist.
The final arguments are object names; this command without any options does not support updating a symbolic ref to point to another ref (see the section called “git-symbolic-ref(1)”). But git update-ref --stdin does have the symref-* commands so that regular refs and symbolic refs can be committed in the same transaction.
If --no-deref is given, <ref> itself is overwritten, rather than the result of following the symbolic pointers.
With -d, it deletes the named <ref> after verifying that it still contains <old-oid>.
With --stdin, update-ref reads instructions from standard input and performs all modifications together. Specify commands of the form:
update SP <ref> SP <new-oid> [SP <old-oid>] LF create SP <ref> SP <new-oid> LF delete SP <ref> [SP <old-oid>] LF verify SP <ref> [SP <old-oid>] LF symref-update SP <ref> SP <new-target> [SP (ref SP <old-target> | oid SP <old-oid>)] LF symref-create SP <ref> SP <new-target> LF symref-delete SP <ref> [SP <old-target>] LF symref-verify SP <ref> [SP <old-target>] LF option SP <opt> LF start LF prepare LF commit LF abort LF
With --create-reflog, update-ref will create a reflog for each ref even if one would not ordinarily be created.
With --batch-updates, update-ref executes the updates in a batch but allows individual updates to fail due to invalid or incorrect user input, applying only the successful updates. However, system-related errors—such as I/O failures or memory issues—will result in a full failure of all batched updates. Any failed updates will be reported in the following format:
rejected SP (<old-oid> | <old-target>) SP (<new-oid> | <new-target>) SP <rejection-reason> LF
Quote fields containing whitespace as if they were strings in C source code; i.e., surrounded by double-quotes and with backslash escapes. Use 40 "0" characters or the empty string to specify a zero value. To specify a missing value, omit the value and its preceding SP entirely.
Alternatively, use -z to specify in NUL-terminated format, without quoting:
update SP <ref> NUL <new-oid> NUL [<old-oid>] NUL create SP <ref> NUL <new-oid> NUL delete SP <ref> NUL [<old-oid>] NUL verify SP <ref> NUL [<old-oid>] NUL symref-update SP <ref> NUL <new-target> [NUL (ref NUL <old-target> | oid NUL <old-oid>)] NUL symref-create SP <ref> NUL <new-target> NUL symref-delete SP <ref> [NUL <old-target>] NUL symref-verify SP <ref> [NUL <old-target>] NUL option SP <opt> NUL start NUL prepare NUL commit NUL abort NUL
In this format, use 40 "0" to specify a zero value, and use the empty string to specify a missing value.
In either format, values can be specified in any form that Git recognizes as an object name. Commands in any other format or a repeated <ref> produce an error. Command meanings are:
symref-create: Create symbolic ref <ref> with <new-target> after verifying that it does not exist.
If all <ref>s can be locked with matching <old-oid>s simultaneously, all modifications are performed. Otherwise, no modifications are performed. Note that while each individual <ref> is updated or deleted atomically, a concurrent reader may still see a subset of the modifications.
If config parameter "core.logAllRefUpdates" is true and the ref is one under "refs/heads/", "refs/remotes/", "refs/notes/", or a pseudoref like HEAD or ORIG_HEAD; or the file "$GIT_DIR/logs/<ref>" exists then git update-ref will append a line to the log file "$GIT_DIR/logs/<ref>" (dereferencing all symbolic refs before creating the log name) describing the change in ref value. Log lines are formatted as:
oldsha1 SP newsha1 SP committer LF
Where "oldsha1" is the 40 character hexadecimal value previously stored in <ref>, "newsha1" is the 40 character hexadecimal value of <new-oid> and "committer" is the committer's name, email address and date in the standard Git committer ident format.
Optionally with -m:
oldsha1 SP newsha1 SP committer TAB message LF
Where all fields are as described above and "message" is the value supplied to the -m option.
An update will fail (without changing <ref>) if the current user is unable to create a new log file, append to the existing log file or does not have committer information available.
Symbolic refs were initially implemented using symbolic links. This is now deprecated since not all filesystems support symbolic links.
This command follows real symlinks only if they start with "refs/": otherwise it will just try to read them and update them as a regular file (i.e. it will allow the filesystem to follow them, but will overwrite such a symlink to somewhere else with a regular filename).
Part of the the section called “git(1)” suite
A dumb server that does not do on-the-fly pack generations must have some auxiliary information files in $GIT_DIR/info and $GIT_OBJECT_DIRECTORY/info directories to help clients discover what references and packs the server has. This command generates such auxiliary files.
Currently the command updates the following files. Please see the section called “gitrepository-layout(5)” for a description of what they are for:
Part of the the section called “git(1)” suite
Invoked by git archive --remote and sends a generated archive to the other end over the Git protocol.
This command is usually not invoked directly by the end user. The UI for the protocol is on the git archive side, and the program pair is meant to be used to get an archive from a remote repository.
In order to protect the privacy of objects that have been removed from history but may not yet have been pruned, git-upload-archive avoids serving archives for commits and trees that are not reachable from the repository's refs. However, because calculating object reachability is computationally expensive, git-upload-archive implements a stricter but easier-to-check set of rules:
Note that rule 3 disallows many cases that do not have any privacy implications. These rules are subject to change in future versions of git, and the server accessed by git archive --remote may or may not follow these exact rules.
If the config option uploadArchive.allowUnreachable is true, these rules are ignored, and clients may use arbitrary sha1 expressions. This is useful if you do not care about the privacy of unreachable objects, or if your object database is already publicly available for access via non-smart-http.
Part of the the section called “git(1)” suite
git-upload-pack [--[no-]strict] [--timeout=<n>] [--stateless-rpc]
[--advertise-refs] <directory>
Invoked by git fetch-pack, learns what objects the other side is missing, and sends them after packing.
This command is usually not invoked directly by the end user. The UI for the protocol is on the git fetch-pack side, and the program pair is meant to be used to pull updates from a remote repository. For push operations, see git send-pack.
When cloning or fetching from a partial repository (i.e., one itself cloned with --filter), the server-side upload-pack may need to fetch extra objects from its upstream in order to complete the request. By default, upload-pack will refuse to perform such a lazy fetch, because git fetch may run arbitrary commands specified in configuration and hooks of the source repository (and upload-pack tries to be safe to run even in untrusted .git directories).
This is implemented by having upload-pack internally set the GIT_NO_LAZY_FETCH variable to 1. If you want to override it (because you are fetching from a partial clone, and you are sure you trust it), you can explicitly set GIT_NO_LAZY_FETCH to 0.
Most Git commands should not be run in an untrusted .git directory (see the section SECURITY in the section called “git(1)”). upload-pack tries to avoid any dangerous configuration options or hooks from the repository it's serving, making it safe to clone an untrusted directory and run commands on the resulting clone.
For an extra level of safety, you may be able to run upload-pack as an alternate user. The details will be platform dependent, but on many systems you can run:
git clone --no-local --upload-pack='sudo -u nobody git-upload-pack' ...
Part of the the section called “git(1)” suite
Most path values contain only one value. However, some can contain multiple values, which are separated by newlines, and are listed in order from highest to lowest priority. Callers should be prepared for any such path value to contain multiple items.
Note that paths are printed even if they do not exist, but not if they are disabled by other environment variables.
the section called “git-commit-tree(1)” the section called “git-tag(1)” the section called “git-config(1)”
Part of the the section called “git(1)” suite
Validates the GPG signature created by git commit -S on the commit objects given on the command line.
Part of the the section called “git(1)” suite
Read each idx file for packed Git archive given on the command line, and verify the idx file and the corresponding pack file.
When specifying the -v option the format used is:
object-name type size size-in-packfile offset-in-packfile
for objects that are not deltified in the pack, and
object-name type size size-in-packfile offset-in-packfile depth base-object-name
for objects that are deltified.
Part of the the section called “git(1)” suite
Validates the gpg signature created by git tag in the tag objects listed on the command line.
Part of the the section called “git(1)” suite
With no options given, the version of git is printed on the standard output.
Note that git --version is identical to git version because the former is internally converted into the latter.
Include additional information about how git was built for diagnostic purposes.
The libraries used to implement the SHA-1 and SHA-256 algorithms are displayed in the form SHA-1: <option> and SHA-256: <option>. Note that the SHA-1 options SHA1_APPLE, SHA1_OPENSSL, and SHA1_BLK do not use a collision detection algorithm and thus may be vulnerable to known SHA-1 collision attacks. When a faster SHA-1 implementation without collision detection is used for only non-cryptographic purposes, the algorithm is displayed in the form non-collision-detecting-SHA-1: <option>.
Part of the the section called “git(1)” suite
This script tries, as much as possible, to display the URLs and FILEs that are passed as arguments, as HTML pages in new tabs on an already opened web browser.
The following browsers (or commands) are currently supported:
Custom commands may also be specified.
The web browser can be specified using a configuration variable passed with the -c (or --config) command-line option, or the web.browser configuration variable if the former is not used.
You can explicitly provide a full path to your preferred browser by setting the configuration variable browser.<tool>.path. For example, you can configure the absolute path to firefox by setting browser.firefox.path. Otherwise, git web--browse assumes the tool is available in PATH.
When the browser, specified by options or configuration variables, is not among the supported ones, then the corresponding browser.<tool>.cmd configuration variable will be looked up. If this variable exists then git web--browse will treat the specified tool as a custom command and will use a shell eval to run the command with the URLs passed as arguments.
When konqueror is specified by a command-line option or a configuration variable, we launch kfmclient to try to open the HTML man page on an already opened konqueror in a new tab if possible.
For consistency, we also try such a trick if browser.konqueror.path is set to something like A_PATH_TO/konqueror. That means we will try to launch A_PATH_TO/kfmclient instead.
If you really want to use konqueror, then you can use something like the following:
[web]
browser = konq
[browser "konq"]
cmd = A_PATH_TO/konquerorNote that these configuration variables should probably be set using the --global flag, for example like this:
$ git config --global web.browser firefox
as they are probably more user specific than repository specific. See the section called “git-config(1)” for more information about this.
Part of the the section called “git(1)” suite
Shows commit logs and diff output each commit introduces.
New users are encouraged to use the section called “git-log(1)” instead. The whatchanged command is essentially the same as the section called “git-log(1)” but defaults to showing the raw format diff output and skipping merges.
The command is primarily kept for historical reasons; fingers of many people who learned Git long before git log was invented by reading the Linux kernel mailing list are trained to type it.
Part of the the section called “git(1)” suite
git worktree add [-f] [--detach] [--checkout] [--lock [--reason <string>]]
[--orphan] [(-b | -B) <new-branch>] <path> [<commit-ish>]
git worktree list [-v | --porcelain [-z]]
git worktree lock [--reason <string>] <worktree>
git worktree move <worktree> <new-path>
git worktree prune [-n] [-v] [--expire <expire>]
git worktree remove [-f] <worktree>
git worktree repair [<path>…]
git worktree unlock <worktree>
Manage multiple working trees attached to the same repository.
A git repository can support multiple working trees, allowing you to check out more than one branch at a time. With git worktree add a new working tree is associated with the repository, along with additional metadata that differentiates that working tree from others in the same repository. The working tree, along with this metadata, is called a "worktree".
This new worktree is called a "linked worktree" as opposed to the "main worktree" prepared by the section called “git-init(1)” or the section called “git-clone(1)”. A repository has one main worktree (if it's not a bare repository) and zero or more linked worktrees. When you are done with a linked worktree, remove it with git worktree remove.
In its simplest form, git worktree add <path> automatically creates a new branch whose name is the final component of <path>, which is convenient if you plan to work on a new topic. For instance, git worktree add ../hotfix creates new branch hotfix and checks it out at path ../hotfix. To instead work on an existing branch in a new worktree, use git worktree add <path> <branch>. On the other hand, if you just plan to make some experimental changes or do testing without disturbing existing development, it is often convenient to create a throwaway worktree not associated with any branch. For instance, git worktree add -d <path> creates a new worktree with a detached HEAD at the same commit as the current branch.
If a working tree is deleted without using git worktree remove, then its associated administrative files, which reside in the repository (see "DETAILS" below), will eventually be removed automatically (see gc.worktreePruneExpire in the section called “git-config(1)”), or you can run git worktree prune in the main or any linked worktree to clean up any stale administrative files.
If the working tree for a linked worktree is stored on a portable device or network share which is not always mounted, you can prevent its administrative files from being pruned by issuing the git worktree lock command, optionally specifying --reason to explain why the worktree is locked.
Create a worktree at <path> and checkout <commit-ish> into it. The new worktree is linked to the current repository, sharing everything except per-worktree files such as HEAD, index, etc. As a convenience, <commit-ish> may be a bare "-", which is synonymous with @{-1}.
If <commit-ish> is a branch name (call it <branch>) and is not found, and neither -b nor -B nor --detach are used, but there does exist a tracking branch in exactly one remote (call it <remote>) with a matching name, treat as equivalent to:
$ git worktree add --track -b <branch> <path> <remote>/<branch>
If the branch exists in multiple remotes and one of them is named by the checkout.defaultRemote configuration variable, we'll use that one for the purposes of disambiguation, even if the <branch> isn't unique across all remotes. Set it to e.g. checkout.defaultRemote=origin to always checkout remote branches from there if <branch> is ambiguous but exists on the origin remote. See also checkout.defaultRemote in the section called “git-config(1)”.
If <commit-ish> is omitted and neither -b nor -B nor --detach used, then, as a convenience, the new worktree is associated with a branch (call it <branch>) named after $(basename <path>). If <branch> doesn't exist, a new branch based on HEAD is automatically created as if -b <branch> was given. If <branch> does exist, it will be checked out in the new worktree, if it's not checked out anywhere else, otherwise the command will refuse to create the worktree (unless --force is used).
If <commit-ish> is omitted, neither --detach, or --orphan is used, and there are no valid local branches (or remote branches if --guess-remote is specified) then, as a convenience, the new worktree is associated with a new unborn branch named <branch> (after $(basename <path>) if neither -b or -B is used) as if --orphan was passed to the command. In the event the repository has a remote and --guess-remote is used, but no remote or local branches exist, then the command fails with a warning reminding the user to fetch from their remote first (or override by using -f/--force).
Repair worktree administrative files, if possible, if they have become corrupted or outdated due to external factors.
For instance, if the main worktree (or bare repository) is moved, linked worktrees will be unable to locate it. Running repair in the main worktree will reestablish the connection from linked worktrees back to the main worktree.
Similarly, if the working tree for a linked worktree is moved without using git worktree move, the main worktree (or bare repository) will be unable to locate it. Running repair within the recently-moved worktree will reestablish the connection. If multiple linked worktrees are moved, running repair from any worktree with each tree's new <path> as an argument, will reestablish the connection to all the specified paths.
If both the main worktree and linked worktrees have been moved or copied manually, then running repair in the main worktree and specifying the new <path> of each linked worktree will reestablish all connections in both directions.
By default, add refuses to create a new worktree when <commit-ish> is a branch name and is already checked out by another worktree, or if <path> is already assigned to some worktree but is missing (for instance, if <path> was deleted manually). This option overrides these safeguards. To add a missing but locked worktree path, specify --force twice.
move refuses to move a locked worktree unless --force is specified twice. If the destination is already assigned to some other worktree but is missing (for instance, if <new-path> was deleted manually), then --force allows the move to proceed; use --force twice if the destination is locked.
remove refuses to remove an unclean worktree unless --force is used. To remove a locked worktree, specify --force twice.
With worktree add <path>, without <commit-ish>, instead of creating a new branch from HEAD, if there exists a tracking branch in exactly one remote matching the basename of <path>, base the new branch on the remote-tracking branch, and mark the remote-tracking branch as "upstream" from the new branch.
This can also be set up as the default behaviour by using the worktree.guessRemote config option.
Link worktrees using relative paths or absolute paths (default). Overrides the worktree.useRelativePaths config option, see the section called “git-config(1)”.
With repair, the linking files will be updated if there's an absolute/relative mismatch, even if the links are correct.
With prune, report all removals.
With list, output additional information about worktrees (see below).
With prune, only expire unused worktrees older than <time>.
With list, annotate missing worktrees as prunable if they are older than <time>.
Worktrees can be identified by path, either relative or absolute.
If the last path components in the worktree's path is unique among worktrees, it can be used to identify a worktree. For example if you only have two worktrees, at /abc/def/ghi and /abc/def/ggg, then ghi or def/ghi is enough to point to the former worktree.
When using multiple worktrees, some refs are shared between all worktrees, but others are specific to an individual worktree. One example is HEAD, which is different for each worktree. This section is about the sharing rules and how to access refs of one worktree from another.
In general, all pseudo refs are per-worktree and all refs starting with refs/ are shared. Pseudo refs are ones like HEAD which are directly under $GIT_DIR instead of inside $GIT_DIR/refs. There are exceptions, however: refs inside refs/bisect, refs/worktree and refs/rewritten are not shared.
Refs that are per-worktree can still be accessed from another worktree via two special paths, main-worktree and worktrees. The former gives access to per-worktree refs of the main worktree, while the latter to all linked worktrees.
For example, main-worktree/HEAD or main-worktree/refs/bisect/good resolve to the same value as the main worktree's HEAD and refs/bisect/good respectively. Similarly, worktrees/foo/HEAD or worktrees/bar/refs/bisect/bad are the same as $GIT_COMMON_DIR/worktrees/foo/HEAD and $GIT_COMMON_DIR/worktrees/bar/refs/bisect/bad.
To access refs, it's best not to look inside $GIT_DIR directly. Instead use commands such as the section called “git-rev-parse(1)” or the section called “git-update-ref(1)” which will handle refs correctly.
By default, the repository config file is shared across all worktrees. If the config variables core.bare or core.worktree are present in the common config file and extensions.worktreeConfig is disabled, then they will be applied to the main worktree only.
In order to have worktree-specific configuration, you can turn on the worktreeConfig extension, e.g.:
$ git config extensions.worktreeConfig true
In this mode, specific configuration stays in the path pointed by git rev-parse --git-path config.worktree. You can add or update configuration in this file with git config --worktree. Older Git versions will refuse to access repositories with this extension.
Note that in this file, the exception for core.bare and core.worktree is gone. If they exist in $GIT_DIR/config, you must move them to the config.worktree of the main worktree. You may also take this opportunity to review and move other configuration that you do not want to share to all worktrees:
See the documentation of extensions.worktreeConfig in the section called “git-config(1)” for more details.
Each linked worktree has a private sub-directory in the repository's $GIT_DIR/worktrees directory. The private sub-directory's name is usually the base name of the linked worktree's path, possibly appended with a number to make it unique. For example, when $GIT_DIR=/path/main/.git the command git worktree add /path/other/test-next next creates the linked worktree in /path/other/test-next and also creates a $GIT_DIR/worktrees/test-next directory (or $GIT_DIR/worktrees/test-next1 if test-next is already taken).
Within a linked worktree, $GIT_DIR is set to point to this private directory (e.g. /path/main/.git/worktrees/test-next in the example) and $GIT_COMMON_DIR is set to point back to the main worktree's $GIT_DIR (e.g. /path/main/.git). These settings are made in a .git file located at the top directory of the linked worktree.
Path resolution via git rev-parse --git-path uses either $GIT_DIR or $GIT_COMMON_DIR depending on the path. For example, in the linked worktree git rev-parse --git-path HEAD returns /path/main/.git/worktrees/test-next/HEAD (not /path/other/test-next/.git/HEAD or /path/main/.git/HEAD) while git rev-parse --git-path refs/heads/master uses $GIT_COMMON_DIR and returns /path/main/.git/refs/heads/master, since refs are shared across all worktrees, except refs/bisect, refs/worktree and refs/rewritten.
See the section called “gitrepository-layout(5)” for more information. The rule of thumb is do not make any assumption about whether a path belongs to $GIT_DIR or $GIT_COMMON_DIR when you need to directly access something inside $GIT_DIR. Use git rev-parse --git-path to get the final path.
If you manually move a linked worktree, you need to update the gitdir file in the entry's directory. For example, if a linked worktree is moved to /newpath/test-next and its .git file points to /path/main/.git/worktrees/test-next, then update /path/main/.git/worktrees/test-next/gitdir to reference /newpath/test-next instead. Better yet, run git worktree repair to reestablish the connection automatically.
To prevent a $GIT_DIR/worktrees entry from being pruned (which can be useful in some situations, such as when the entry's worktree is stored on a portable device), use the git worktree lock command, which adds a file named locked to the entry's directory. The file contains the reason in plain text. For example, if a linked worktree's .git file points to /path/main/.git/worktrees/test-next then a file named /path/main/.git/worktrees/test-next/locked will prevent the test-next entry from being pruned. See the section called “gitrepository-layout(5)” for details.
When extensions.worktreeConfig is enabled, the config file .git/worktrees/<id>/config.worktree is read after .git/config is.
The worktree list command has two output formats. The default format shows the details on a single line with columns. For example:
$ git worktree list /path/to/bare-source (bare) /path/to/linked-worktree abcd1234 [master] /path/to/other-linked-worktree 1234abc (detached HEAD)
The command also shows annotations for each worktree, according to its state. These annotations are:
$ git worktree list /path/to/linked-worktree abcd1234 [master] /path/to/locked-worktree acbd5678 (brancha) locked /path/to/prunable-worktree 5678abc (detached HEAD) prunable
For these annotations, a reason might also be available and this can be seen using the verbose mode. The annotation is then moved to the next line indented followed by the additional information.
$ git worktree list --verbose
/path/to/linked-worktree abcd1234 [master]
/path/to/locked-worktree-no-reason abcd5678 (detached HEAD) locked
/path/to/locked-worktree-with-reason 1234abcd (brancha)
locked: worktree path is mounted on a portable device
/path/to/prunable-worktree 5678abc1 (detached HEAD)
prunable: gitdir file points to non-existent locationNote that the annotation is moved to the next line if the additional information is available, otherwise it stays on the same line as the worktree itself.
The porcelain format has a line per attribute. If -z is given then the lines are terminated with NUL rather than a newline. Attributes are listed with a label and value separated by a single space. Boolean attributes (like bare and detached) are listed as a label only, and are present only if the value is true. Some attributes (like locked) can be listed as a label only or with a value depending upon whether a reason is available. The first attribute of a worktree is always worktree, an empty line indicates the end of the record. For example:
$ git worktree list --porcelain worktree /path/to/bare-source bare worktree /path/to/linked-worktree HEAD abcd1234abcd1234abcd1234abcd1234abcd1234 branch refs/heads/master worktree /path/to/other-linked-worktree HEAD 1234abc1234abc1234abc1234abc1234abc1234a detached worktree /path/to/linked-worktree-locked-no-reason HEAD 5678abc5678abc5678abc5678abc5678abc5678c branch refs/heads/locked-no-reason locked worktree /path/to/linked-worktree-locked-with-reason HEAD 3456def3456def3456def3456def3456def3456b branch refs/heads/locked-with-reason locked reason why is locked worktree /path/to/linked-worktree-prunable HEAD 1233def1234def1234def1234def1234def1234b detached prunable gitdir file points to non-existent location
Unless -z is used any "unusual" characters in the lock reason such as newlines are escaped and the entire reason is quoted as explained for the configuration variable core.quotePath (see the section called “git-config(1)”). For Example:
$ git worktree list --porcelain ... locked "reason\nwhy is locked" ...
You are in the middle of a refactoring session and your boss comes in and demands that you fix something immediately. You might typically use the section called “git-stash(1)” to store your changes away temporarily, however, your working tree is in such a state of disarray (with new, moved, and removed files, and other bits and pieces strewn around) that you don't want to risk disturbing any of it. Instead, you create a temporary linked worktree to make the emergency fix, remove it when done, and then resume your earlier refactoring session.
$ git worktree add -b emergency-fix ../temp master $ pushd ../temp # ... hack hack hack ... $ git commit -a -m 'emergency fix for boss' $ popd $ git worktree remove ../temp
Multiple checkout in general is still experimental, and the support for submodules is incomplete. It is NOT recommended to make multiple checkouts of a superproject.
Part of the the section called “git(1)” suite
Creates a tree object using the current index. The name of the new tree object is printed to standard output.
The index must be in a fully merged state.
Conceptually, git write-tree sync()s the current index contents into a set of tree files. In order to have that match what is actually in your directory right now, you need to have done a git update-index phase before you did the git write-tree.
Part of the the section called “git(1)” suite
scalar clone [--single-branch] [--branch <main-branch>] [--full-clone]
[--[no-]src] [--[no-]tags] [--[no-]maintenance] <url> [<enlistment>]
scalar list
scalar register [--[no-]maintenance] [<enlistment>]
scalar unregister [<enlistment>]
scalar run ( all | config | commit-graph | fetch | loose-objects | pack-files ) [<enlistment>]
scalar reconfigure [--maintenance=(enable|disable|keep)] [ --all | <enlistment> ]
scalar diagnose [<enlistment>]
scalar delete <enlistment>
Scalar is a repository management tool that optimizes Git for use in large repositories. Scalar improves performance by configuring advanced Git settings, maintaining repositories in the background, and helping to reduce data sent across the network.
An important Scalar concept is the enlistment: this is the top-level directory of the project. It usually contains the subdirectory src/ which is a Git worktree. This encourages the separation between tracked files (inside src/) and untracked files, such as build artifacts (outside src/). When registering an existing Git worktree with Scalar whose name is not src, the enlistment will be identical to the worktree.
The scalar command implements various subcommands, and different options depending on the subcommand. With the exception of clone, list and reconfigure --all, all subcommands expect to be run in an enlistment.
The following options can be specified before the subcommand:
Clones the specified repository, similar to the section called “git-clone(1)”. By default, only commit and tree objects are cloned. Once finished, the worktree is located at <enlistment>/src.
The sparse-checkout feature is enabled (except when run with --full-clone) and the only files present are those in the top-level directory. Use git sparse-checkout set to expand the set of directories you want to see, or git sparse-checkout disable to expand to all files (see the section called “git-sparse-checkout(1)” for more details). You can explore the subdirectories outside your sparse-checkout by using git ls-tree HEAD[:<directory>].
Clone only the history leading to the tip of a single branch, either specified by the --branch option or the primary branch remote's HEAD points at.
Further fetches into the resulting repository will only update the remote-tracking branch for the branch this option was used for the initial cloning. If the HEAD at the remote did not point at any branch when --single-branch clone was made, no remote-tracking branch is created.
Adds the enlistment's repository to the list of registered repositories and starts background maintenance. If <enlistment> is not provided, then the enlistment associated with the current working directory is registered.
Note: when this subcommand is called in a worktree that is called src/, its parent directory is considered to be the Scalar enlistment. If the worktree is not called src/, it itself will be considered to be the Scalar enlistment.
Run the given maintenance task (or all tasks, if all was specified). Except for all and config, this subcommand simply hands off to the section called “git-maintenance(1)” (mapping fetch to prefetch and pack-files to incremental-repack).
These tasks are run automatically as part of the scheduled maintenance, as soon as the repository is registered with Scalar. It should therefore not be necessary to run this subcommand manually.
The config task is specific to Scalar and configures all those opinionated default settings that make Git work more efficiently with large repositories. As this task is run as part of scalar clone automatically, explicit invocations of this task are rarely needed.
After a Scalar upgrade, or when the configuration of a Scalar enlistment was somehow corrupted or changed by mistake, this subcommand allows to reconfigure the enlistment.
When reporting issues with Scalar, it is often helpful to provide the information gathered by this command, including logs and certain statistics describing the data shape of the current enlistment.
The output of this command is a .zip file that is written into a directory adjacent to the worktree in the src directory.
Part of the the section called “git(1)” suite
[1] Permitted pathnames have the form bf/fe/30/…/680d5a…: a sequence of directory names of two hexadecimal digits each followed by a filename with the rest of the object ID.